<!Doctype html>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<meta name="viewport" content="width=device-width, initial-scale=1.0" />
	<title>Express 4.x API 中文文档 | 菜鸟教程</title>

  <meta name='robots' content='max-image-preview:large' />
<link rel='stylesheet' id='classic-theme-styles-css' href='../0/classic-themes.min.css?ver=6.2' type='text/css' media='all' />
<link rel="canonical" href="../w3cnote/express-4-x-api.html" />
<meta name="keywords" content="Express 4.x API 中文文档">
<meta name="description" content="express()  express()用来创建一个Express的程序。express()方法是express模块导出的顶层方法。   var express = require(&#039;express&#039;); var app = express();   Methods  express.static(root, [options])  express.static是Express中唯一的内建中间件。它以server-s..">
		
	<link rel="shortcut icon" href="https://static.runoob.com/images/favicon.ico">
	<link rel="stylesheet" href="../0/style.css?v=1.170" type="text/css" media="all" />	
	<link rel="stylesheet" href="../0/font-awesome.min.css" media="all" />	
  <!--[if gte IE 9]><!-->
  <script src=""></script>
  <!--<![endif]-->
  <!--[if lt IE 9]>
     <script src=""></script>
     <script src=""></script>
  <![endif]-->
  <link rel="apple-touch-icon" href="https://static.runoob.com/images/icon/mobile-icon.png"/>
  <meta name="apple-mobile-web-app-title" content="菜鸟教程">
</head>
<body>

<!--  头部 -->
<div class="container logo-search">

  <div class="col search row-search-mobile">
    <form action="index.php">
      <input class="placeholder" placeholder="搜索……" name="s" autocomplete="off">
      
    </form>
  </div>

  <div class="row">
    <div class="col logo">
      <h1><a href="../">菜鸟教程 -- 学的不仅是技术，更是梦想！</a></h1>
    </div>
        <div class="col right-list"> 
    <button class="btn btn-responsive-nav btn-inverse" data-toggle="collapse" data-target=".nav-main-collapse" id="pull" style=""> <i class="fa fa-navicon"></i> </button>
    </div>
        
    <div class="col search search-desktop last">
      <div class="search-input" >
      <form action="//www.runoob.com/" target="_blank">
        <input class="placeholder" id="s" name="s" placeholder="搜索……"  autocomplete="off" style="height: 44px;">
      </form>
      
      </div>
    </div>
  </div>
</div>



<!-- 导航栏 -->
<div class="container navigation">
    <div class="row">
        <div class="col nav">
            

                        <ul class="pc-nav" id="note-nav">
                <li><a href="../">首页</a></li>
                <li><a href="../w3cnote">笔记首页</a></li>
                <li><a href="../w3cnote/android-tutorial-intro.html" title="Android 基础入门教程">Android</a></li>
                <li><a href="../w3cnote/es6-tutorial.html" title="ES6 教程">ES6 教程</a></li>
                <li><a href="../w3cnote/ten-sorting-algorithm.html" title="排序算法">排序算法</a></li>
                <li><a href="../w3cnote/hadoop-tutorial.html" title="Hadoop 教程">Hadoop</a></li>
                <li><a href="../w3cnote/zookeeper-tutorial.html" title="Zookeeper 教程">Zookeeper</a></li>
                <li><a href="../w3cnote/verilog-tutorial.html" title="Verilog 教程">Verilog</a></li>
                <li><a href="../w3cnote_genre/code" title="编程技术">编程技术</a></li> 
                <li><a href="../w3cnote_genre/coderlife" title="程序员人生">程序员人生</a></li>
                
                <!--<li><a href="javascript:;" class="runoob-pop">登录</a></li>
                
                
                        <li>
                <a style="font-weight:bold;" href="../linux/linux-tutorial.html#yunserver" target="_blank" onclick="_hmt.push(['_trackEvent', 'aliyun', 'click', 'aliyun'])" title="kkb">云服务器</a>
                </li>
                <li><a href="http://gk.link/a/104mQ" target="_blank" style="font-weight: bold;"onclick="_hmt.push(['_trackEvent', '极客时间', 'click', 'jike'])" title="我的圈子">极客时间</a></li>
            
                
                <li><a target="_blank" href="../shoppinglist" rel="nofollow">知识店铺</a></li> 
        -->
            </ul>
                        
              
            <ul class="mobile-nav">
                <li><a href="../w3cnote">首页</a></li>
                <li><a href="../w3cnote_genre/android" target="_blank" title="Android 基础入门教程">Android</a></li>
                <li><a href="../w3cnote/es6-tutorial.html" target="_blank" title="ES6 教程">ES6</a></li>
                <li><a href="../w3cnote_genre/joke" target="_blank" title="程序员笑话">逗乐</a></li>
                
                <a href="javascript:void(0)" class="search-reveal">Search</a> 
            </ul>
            
        </div>
    </div>
</div>


<!--  内容  -->
<div class="container main">
	<div class="row">

		<div class="col middle-column big-middle-column">
	 			<div class="article">
			<div class="article-heading">
				<h2>Express 4.x API 中文文档</h2>				<h3><em>分类</em> <a href="../w3cnote_genre/code" title="编程技术" >编程技术</a> </h3>
			</div>
			<div class="article-body note-body">
				<div class="article-intro">
					<h2>express()</h2>

<p><strong>express()</strong>用来创建一个Express的程序。<strong>express()</strong>方法是<strong><em>express</em></strong>模块导出的顶层方法。
</p>
<pre>
var express = require('express');
var app = express();
</pre>

<h3>Methods</h3>

<h4>express.static(root, [options])</h4>

<p><strong>express.static</strong>是Express中唯一的内建中间件。它以<a target="_blank" href="https://github.com/expressjs/serve-static">server-static</a>模块为基础开发，负责托管 Express 应用内的静态资源。
参数<strong>root</strong>为静态资源的所在的根目录。
参数<strong>options</strong>是可选的，支持以下的属性：</p>

<table class="reference">
<thead>
<tr>
<th style="text-align: center">属性</th>
<th style="text-align: center">描述</th>
<th style="text-align: center">类型</th>
<th style="text-align: center">默认值</th>
</tr>
</thead>

<tbody>
<tr>
<td style="text-align: center">dotfiles</td>
<td style="text-align: center">是否响应点文件。供选择的值有&quot;allow&quot;，&quot;deny&quot;和&quot;ignore&quot;</td>
<td style="text-align: center">String</td>
<td style="text-align: center">&quot;ignore&quot;</td>
</tr>
<tr>
<td style="text-align: center">etag</td>
<td style="text-align: center">使能或者关闭etag</td>
<td style="text-align: center">Boolean</td>
<td style="text-align: center">true</td>
</tr>
<tr>
<td style="text-align: center">extensions</td>
<td style="text-align: center">设置文件延期回退</td>
<td style="text-align: center">Boolean</td>
<td style="text-align: center">true</td>
</tr>
<tr>
<td style="text-align: center">index</td>
<td style="text-align: center">发送目录索引文件。设置false将不发送。</td>
<td style="text-align: center">Mixed</td>
<td style="text-align: center">&quot;index.html&quot;</td>
</tr>
<tr>
<td style="text-align: center">lastModified</td>
<td style="text-align: center">设置文件在系统中的最后修改时间到<strong>Last-Modified</strong>头部。可能的取值有<strong>false</strong>和<strong>true</strong>。</td>
<td style="text-align: center">Boolean</td>
<td style="text-align: center">true</td>
</tr>
<tr>
<td style="text-align: center">maxAge</td>
<td style="text-align: center">在Cache-Control头部中设置<strong>max-age</strong>属性，精度为毫秒(ms)或则一段<a target="_blank" href="https://www.npmjs.org/package/ms">ms format</a>的字符串</td>
<td style="text-align: center">Number</td>
<td style="text-align: center">0</td>
</tr>
<tr>
<td style="text-align: center">redirect</td>
<td style="text-align: center">当请求的pathname是一个目录的时候，重定向到尾随&quot;/&quot;</td>
<td style="text-align: center">Boolean</td>
<td style="text-align: center">true</td>
</tr>
<tr>
<td style="text-align: center">setHeaders</td>
<td style="text-align: center">当响应静态文件请求时设置headers的方法</td>
<td style="text-align: center">Funtion</td>
<td style="text-align: center">&nbsp;</td>
</tr>
</tbody>
</table>

<p>如果你想获得更多关于使用中间件的细节，你可以查阅<a target="_blank" href="http://expressjs.com/starter/static-files.html">Serving static files in Express</a>。</p>

<h2>Application()</h2>

<p><strong>app</strong>对象一般用来表示Express程序。通过调用Express模块导出的顶层的<strong>express()</strong>方法来创建它:
</p>
<pre>
var express = require('express');
var app = express();

app.get('/', function(req, res) {
    res.send('hello world!');
});

app.listen(3000);
</pre>
<p>
</strong>app 对象具有以下的方法：</p>

<ul>
<li> 路由HTTP请求；具体可以看<a href="#toc_19">app.METHOD</a>和<a href="#toc_20">app.param</a>这两个例子。</li>
<li> 配置中间件；具体请看<a href="#toc_24">app.route</a>。</li>
<li> 渲染HTML视图；具体请看<a href="#toc_23">app.render</a>。</li>
<li> 注册模板引擎；具体请看<a href="#toc_15">app.engine</a>。</li>
</ul>

<p>它还有一些属性设置，这些属性可以改变程序的行为。获得更多的信息，可以查阅<a href="#app.settings.table">Application settings</a>。</p>

<h3>Properties</h3>


<h4>app.locals</h4>

<p>
app.locals对象是一个javascript对象，它的属性就是程序本地的变量。
</p>
<pre>
app.locals.title
// =&gt; 'My App'
app.locals.email
// =&gt; 'me@myapp.com'
</pre>
<p>
一旦设定，<strong>app.locals</strong>的各属性值将贯穿程序的整个生命周期，与其相反的是 <strong>res.locals</strong> ，它只在这次请求的生命周期中有效。</p>

<p>在程序中，你可以在渲染模板时使用这些本地变量。它们是非常有用的，可以为模板提供一些有用的方法，以及<strong>app</strong>级别的数据。通过<strong>req.app.locals</strong>(具体查看<a href="#toc_28">req.app</a>)，Locals可以在中间件中使用。
</p>
<pre>
app.locals.title = 'My App';
app.locals.strftime = require('strftime');
app.locals.email = 'me@myapp.com';
</pre>

<h4 id="toc_7">app.mountpath</h4>

<p><strong>app.mountpath</strong>属性是子程序挂载的路径模式。</p>

<blockquote>
<p>一个子程序是一个<strong>express</strong>的实例，其可以被用来作为路由句柄来处理请求。</p>
</blockquote>
<pre>
var express = require('express');
var app = express(); // the main app
var admin = express(); // the sub app
admin.get('/', function(req, res) {
    console.log(admin.mountpath); // /admin
    res.send('Admin Homepage');
});
app.use('/admin', admin); // mount the sub app
</pre><p>
它和req对象的<a href="#toc_29">req.baseUrl</a>
)属性比较相似，除了req.baseUrl是匹配的URL路径，而不是匹配的模式。如果一个子程序被挂载在多条路径模式，app.mountpath就是一个关于挂载路径模式项的列表，如下面例子所示。
</p><pre>
var admin = express();

admin.get('/', function (req, res) {
  console.log(admin.mountpath); // [ '/adm*n', '/manager' ]
  res.send('Admin Homepage');
});

var secret = express();
secret.get('/', function (req, res) {
  console.log(secret.mountpath); // /secr*t
  res.send('Admin Secret');
});

admin.use('/secr*t', secret); // load the 'secret' router on '/secr*t', on the 'admin' sub app
app.use(['/adm*n', '/manager'], admin); // load the 'admin' router on '/adm*n' and '/manager', on the parent app
</pre>


<h2>Events</h2><h3>app.on(&#39;mount&#39;, callback(parent))</h3><p>
当子程序被挂载到父程序时，mount事件被发射。父程序对象作为参数，传递给回调方法。</p>
<pre>
var admin = express();
admin.on('mount', function(parent) {
    console.log('Admin Mounted');
    console.log(parent); // refers to the parent app
});
admin.get('/', function(req, res) {
    res.send('Admin Homepage');
});
app.use('/admin', admin);
</pre>

<h3>Methods</h3>

<h4>app.all(path, callback[, callback ...]</h4>

<p><strong>app.all</strong>方法和标准的<strong>app.METHOD()</strong>方法相似，除了它匹配所有的HTTP动词。
对于给一个特殊前缀映射一个全局的逻辑处理，或者无条件匹配，它是很有效的。例如，如果你把下面内容放在所有其他的路由定义的前面，它要求所有从这个点开始的路由需要认证和自动加载一个用户。记住这些回调并不是一定是终点:<strong>loadUser</strong>可以在完成了一个任务后，调用<strong>next()</strong>方法来继续匹配随后的路由。
</p><pre>app.all('*', requireAuthentication, loadUser);</pre><p>
或者这种相等的形式:</p>
<pre>
app.all('*', requireAuthentication);
app.all('*', loadUser);
</pre><p>
另一个例子是全局的白名单方法。这个例子和前面的很像，然而它只是限制以<strong>/api</strong>开头的路径。
</p>
<pre>
app.all('/api/*', requireAuthentication);
</pre>

<h4>app.delete(path, callback[, callback ...])</h4>

<p>路由<strong>HTTP DELETE</strong>请求到有特殊回调方法的特殊的路径。获取更多的信息，可以查阅<a target="_blank" href="http://expressjs.com/guide/routing.html">routing guide</a>。
你可以提供多个回调函数，它们的行为和中间件一样，除了这些回调可以通过调用<strong>next(&#39;router&#39;)</strong>来绕过剩余的路由回调。你可以使用这个机制来为一个路由设置一些前提条件，如果不能满足当前路由的处理条件，那么你可以传递控制到随后的路由。</p>
<pre>
app.delete('/', function(req, res) {
    res.send('DELETE request to homepage');
});
</pre>
<h4>app.disable(name)</h4>

<p>设置类型为布尔的设置名为<strong>name</strong>的值为<strong>false</strong>，此处的<strong>name</strong>是<a href="#app.settings.table">app settings table</a>中各属性的一个。调用<strong>app.set(&#39;foo&#39;, false)</strong>和调用<strong>app.disable(&#39;foo&#39;)</strong>是等价的。
比如:</p>
<pre>
app.disable('trust proxy');
app.get('trust proxy');
// =&gt; false
</pre>

<h4>app.disabled(name)</h4>

<p>返回<strong>true</strong>如果布尔类型的设置值<strong>name</strong>被禁用为<strong>false</strong>，此处的<strong>name</strong>是<a target="_blank" href="#app.settings.table">app settings table</a>中各属性的一个。</p>
<pre>
app.disabled('trust proxy');
// =&gt; true
app.enable('trust proxy');
app.disabled('trust proxy');
// =&gt; false
</pre>
<h4>app.enable(name)</h4>

<p>设置布尔类型的设置值<strong>name</strong>为<strong>true</strong>，此处的<strong>name</strong>是<ahref="#app.settings.table">app settings table</a>中各属性的一个。调用<strong>app.set(&#39;foo&#39;, true)</strong>和调用<strong>app.enable(&#39;foo&#39;)</strong>是等价的。</p>
<pre>
app.enable('trust proxy');
app.get('trust proxy');
// =&gt; true
</pre>

<h4>app.enabled(name)</h4>

<p>返回<strong>true</strong>如果布尔类型的设置值<strong>name</strong>被启动为<strong>true</strong>，此处的<strong>name</strong>是<a target="_blank" href="#app.settings.table">app settings table</a>中各属性的一个。</p>
<pre>
app.enabled('trust proxy');
// =&gt; false
app.enable('trust proxy');
app.enabled('trust proxy');
// =&gt; true
</pre>
<h4 id="toc_15">app.engine(ext, callback)</h4>

<p>注册给定引擎的回调，用来渲染处理ext文件。
默认情况下，Express需要使用<strong>require()</strong>来加载基于文件扩展的引擎。例如，如果你尝试渲染一个<strong>foo.jade</strong>文件，Express在内部调用下面的内容，同时缓存<strong>require()</strong>结果供随后的调用，来加速性能。
</p>
<pre>
app.engine('jade', require('jade').__express);
</pre><p>
使用下面的方法对于那些没有提供开箱即用的<strong>.__express</strong>方法的模板，或者你希望使用不同的模板引擎扩展。
比如，使用EJS模板引擎来渲染<strong>.html</strong>文件：</p>
<pre>app.engine('html', require('ejs').renderFile);</pre><p>
在这个例子中，EJS提供了一个<strong>.renderFile</strong>方法，这个方法满足了Express规定的签名规则：<strong>(path, options, callback)</strong>，然而记住在内部它只是<strong>ejs.__express</strong>的一个别名，所以你可以在不做任何事的情况下直接使用<strong>.ejs</strong>扩展。
一些模板引擎没有遵循这种规范，<a target="_blank" href="https://github.com/tj/consolidate.js">consolidate.js</a>库映射模板引擎以下面的使用方式，所以他们可以无缝的和Express工作。</p>
<pre>
var engines = require('consolidate');
app.engine('haml', engines.haml);
app.engine('html', engines.hogan);
</pre>

<h4 id="toc_16">app.get(name)</h4>

<p>获得设置名为<strong>name</strong>的app设置的值，此处的<strong>name</strong>是<a target="_blank" href="#app.settings.table">app settings table</a>中各属性的一个。
如下：</p><pre>
app.get('title');
// =&gt; undefined
app.set('title', 'My Site');
app.get('title');
// =&gt; 'My Site'
</pre>

<h4 id="toc_17">app.get(path, callback [, callback ...])</h4>

<p>路由<strong>HTTP GET</strong>请求到有特殊回调的特殊路径。获取更多的信息，可以查阅<a target="_blank" href="http://expressjs.com/guide/routing.html">routing guide</a>。
你可以提供多个回调函数，它们的行为和中间件一样，除了这些回调可以通过调用<strong>next(&#39;router&#39;)</strong>来绕过剩余的路由回调。你可以使用这个机制来为一个路由设置一些前提条件，如果请求没能满足当前路由的处理条件，那么传递控制到随后的路由。</p>
<pre>
app.get('/', function(req, res) {
    res.send('GET request to homepage');
});
</pre>

<h4 id="toc_18">app.listen(port, [hostname], [backlog], [callback])</h4>

<p>绑定程序监听端口到指定的主机和端口号。这个方法和<strong>Node</strong>中的<a target="_blank" href="http://nodejs.org/api/http.html#http_server_listen_port_hostname_backlog_callback">http.Server.listen()</a>是一样的。</p>
<pre>
var express = require('express');
var app = express();
app.listen(3000);
</pre>
<p>通过调用<strong>express()</strong>返回得到的<strong>app</strong>实际上是一个JavaScript的<strong>Function</strong>，被设计用来作为一个回调传递给<strong>Node HTTP servers</strong>来处理请求。这样，其就可以很简便的基于同一份代码提供http和https版本，所以app没有从这些继承(它只是一个简单的回调)。</p>
<pre>
var express = require('express');
var https = require('https');
var http = require('http');
http.createServer(app).listen(80);
https.createServer(options, app).listen(443);</pre>

<p>app.listen()方法是下面所示的一个便利的方法(只针对HTTP协议):</p>
<pre>
app.listen = function() {
    var server = http.createServer(this);
    return server.listen.apply(server, arguments);
};
</pre>
<h4 id="toc_19">app.METHOD(path, callback [, callback ...])</h4>

<p>路由一个HTTP请求，<strong>METHOD</strong>是这个请求的HTTP方法，比如<strong>GET</strong>，<strong>PUT</strong>，<strong>POST</strong>等等，注意是小写的。所以，实际的方法是<strong>app.get()</strong>，<strong>app.post()</strong>，<strong>app.put()</strong>等等。下面有关于方法的完整的表。</p><p>
获取更多信息，请看<a target="_blank" href="http://expressjs.com/guide/routing.html">routing guide</a>。
Express支持下面的路由方法，对应与同名的HTTP方法：</p>

<table style="border:0px;background:node">
    <tbody>
        <tr>
            <td style="background:none;border:0px;">
                <ul>
                <li>checkout</li>
                <li>connect</li>
                <li>copy</li>
                <li>delete</li>
                <li>get</li>
                <li>head</li>
                <li>lock</li>
                <li>merge</li>
                <li>mkactivity</li>
                <ul>
            </td>
            <td style="background:none;border:0px;">
               <ul>
                <li>mkcol</li>
                <li>move</li>
                <li>m-search</li>
                <li>notify</li>
                <li>options</li>
                <li>patch</li>
                <li>post</li>
                <li>propfind</li>
                <li>proppatch</li>
                <ul>
            </td>
                        <td style="background:none;border:0px;">
               <ul>
                <li>purege</li>
                <li>put</li>
                <li>report</li>
                <li>search</li>
                <li>subscribe</li>
                <li>trace</li>
                <li>unlock</li>
                <li>unsubscribe</li>
                <ul>
            </td>
        <tr>
    </tbody>
</table>

<blockquote>
<p>如果使用上述方法时，导致了无效的javascript的变量名，可以使用中括号符号，比如,<strong>app[&#39;m-search&#39;](&#39;/&#39;, function ...</strong></p>
</blockquote>

<p>你可以提供多个回调函数，它们的行为和中间件一样，除了这些回调可以通过调用<strong>next(&#39;router&#39;)</strong>来绕过剩余的路由回调。你可以使用这个机制来为一个路由设置一些前提条件，如果请求没有满足当前路由的处理条件，那么传递控制到随后的路由。</p>

<blockquote>
<p>本API文档把使用比较多的HTTP方法<strong>app.get()</strong>，<strong>app.post</strong>，<strong>app.put()</strong>，<strong>app.delete()</strong>作为一个个单独的项进行说明。然而，其他上述列出的方法以完全相同的方式工作。</p>
</blockquote>

<p><strong>app.all()</strong>是一个特殊的路由方法，它不属于HTTP协议中的规定的方法。它为一个路径加载中间件，其对所有的请求方法都有效。</p>
<pre>
app.all('/secret', function (req, res) {
    console.log('Accessing the secret section...');
    next(); // pass control to the next handler
});
</pre>
<h4 id="toc_20">app.param([name], callback)</h4>

<p>给路由参数添加回调触发器，这里的<strong>name</strong>是参数名或者参数数组，<strong>function</strong>是回调方法。回调方法的参数按序是<strong>请求对象</strong>，<strong>响应对象</strong>，<strong>下个中间件</strong>，<strong>参数值</strong>和<strong>参数名</strong>。
如果<strong>name</strong>是数组，会按照各个参数在数组中被声明的顺序将回调触发器注册下来。还有，对于除了最后一个参数的其他参数，在他们的回调中调用<strong>next()</strong>来调用下个声明参数的回调。对于最后一个参数，在回调中调用<strong>next()</strong>将调用位于当前处理路由中的下一个中间件，如果<strong>name</strong>只是一个<strong>string</strong>那就和它是一样的(就是说只有一个参数，那么就是最后一个参数，和数组中最后一个参数是一样的)。
例如，当<strong>:user</strong>出现在路由路径中，你可以映射用户加载的逻辑处理来自动提供<strong>req.user</strong>给这个路由，或者对输入的参数进行验证。
</p>
<pre>
app.param('user', function(req, res, next, id) {
    User.find(id, function(error, user) {
        if (err) {
            next(err);
        }
        else if (user){
            req.user = user;
        } else {
            next(new Error('failed to load user'));
        }
    });
});
</pre><p>
对于<strong>Param</strong>的回调定义的路由来说，他们是局部的。它们不会被挂载的app或者路由继承。所以，定义在<strong>app</strong>上的<strong>Param</strong>回调只有是在<strong>app</strong>上的路由具有这个路由参数时才起作用。</p><p>
在定义<strong>param</strong>的路由上，<strong>param</strong>回调都是第一个被调用的，它们在一个请求-响应循环中都会被调用一次并且只有一次，即使多个路由都匹配，如下面的例子：</p>
<pre>
app.param('id', function(req, res, next, id) {
    console.log('CALLED ONLY ONCE');
    next();
});
app.get('/user/:id', function(req, res, next) {
    console.log('although this matches');
    next();
});
app.get('/user/:id', function(req, res) {
    console.log('and this mathces too');
    res.end();
});
</pre><p>
当GET /user/42，得到下面的结果:</p>
<pre>
CALLED ONLY ONCE
although this matches
and this matches too
</pre><pre>app.param(['id', 'page'], function(req, res, next, value) {
    console.log('CALLED ONLY ONCE with', value);
    next();
});
app.get('/user/:id/:page', function(req. res, next) {
    console.log('although this matches');
    next();
});
app.get('/user/:id/:page', function (req, res, next) {
    console.log('and this matches too');
    res.end();
});
</pre><p>
当执行GET /user/42/3，结果如下：</p>
<pre>
CALLED ONLY ONCE with 42
CALLED ONLY ONCE with 3
although this matches
and this mathes too
</pre>
<blockquote>
<p>下面章节描述的<strong>app.param(callback)</strong>在v4.11.0之后被弃用。</p>
</blockquote>

<p>通过只传递一个回调参数给<strong>app.param(name, callback)</strong>方法，<strong>app.param(naem, callback)</strong>方法的行为将被完全改变。这个回调参数是关于<strong>app.param(name, callback)</strong>该具有怎样的行为的一个自定义方法，这个方法必须接受两个参数并且返回一个中间件。
这个回调的第一个参数就是需要捕获的url的参数名，第二个参数可以是任一的JavaScript对象，其可能在实现返回一个中间件时被使用。
这个回调方法返回的中间件决定了当URL中包含这个参数时所采取的行为。
在下面的例子中，<strong>app.param(name, callback)</strong>参数签名被修改成了<strong>app.param(name, accessId)</strong>。替换接受一个参数名和回调，<strong>app.param()</strong>现在接受一个参数名和一个数字。</p>
<pre>
var express = require('express');
var app = express();
app.param(function(param, option){
    return function(req, res, next, val) {
        if (val == option) {
            next();
        }
        else {
            res.sendStatus(403);
        }
    }
});
app.param('id', 1337);
app.get('/user/:id', function(req, res) {
    res.send('Ok');
});
app.listen(3000, function() {
    console.log('Ready');
}); 
</pre>
<p>在这个例子中，app.param(name, callback)参数签名保持和原来一样，但是替换成了一个中间件，定义了一个自定义的数据类型检测方法来检测user id的类型正确性。</p>
<pre>
app.param(function(param, validator) {
    return function(req, res, next, val) {
        if (validator(val)) {
            next();
        }
        else {
            res.sendStatus(403);
        }
    }
});
app.param('id', function(candidate) {
    return !isNaN(parseFloat(candidate)) &amp;&amp; isFinite(candidate);
});
</pre>
<blockquote>
<p>在使用正则表达式来，不要使用<strong>.</strong>。例如，你不能使用<strong>/user-.+/</strong>来捕获<strong>user-gami</strong>，用使用<strong>[\\s\\S]</strong>或者<strong>[\\w\\&gt;W]</strong>来代替(正如<strong>/user-[\\s\\S]+/</strong>)。</p>
<pre>
//captures '1-a_6' but not '543-azser-sder'
router.get('/[0-9]+-[[\\w]]*', function); 
//captures '1-a_6' and '543-az(ser"-sder' but not '5-a s'
router.get('/[0-9]+-[[\\S]]*', function); 
//captures all (equivalent to '.*')
router.get('[[\\s\\S]]*', function); 
</pre>
</blockquote>

<h4 id="toc_21">app.path()</h4>

<p>通过这个方法可以得到<strong>app</strong>典型的路径，其是一个<strong>string</strong>。</p>
<pre>
 var app = express()
      , blog = express()
      , blogAdmin = express();
    app.use('/blog', blog);
    app.use('/admin', blogAdmin);
    console.log(app.path()); // ''
    console.log(blog.path()); // '/blog'
    console.log(blogAdmin.path()); // '/blog/admin'
</pre>

<p>如果app挂载很复杂下，那么这个方法的行为也会很复杂：一种更好用的方式是使用req.baseUrl来获得这个app的典型路径。
</p>
<h4>app.post(path, callback, [callback ...])</h4><p>
路由HTTP POST请求到有特殊回调的特殊路径。获取更多的信息，可以查阅[routing guide](http://expressjs.com/guide/routing.html)。</p><p>
你可以提供多个回调函数，它们的行为和中间件一样，除了这些回调可以通过调用next(&#39;router&#39;)来绕过剩余的路由回调。你可以使用这个机制来为一个路由设置一些前提条件，如果请求没能满足当前路由的处理条件，那么传递控制到随后的路由。</p>
<pre>
app.post('/', function(req, res) {
    res.send('POST request to homepage')
});
</pre>
<h4 id="toc_22">app.put(path, callback, [callback ...])</h4>

<p>路由<strong>HTTP PUT</strong>请求到有特殊回调的特殊路径。获取更多的信息，可以查阅<a target="_blank" href="http://expressjs.com/guide/routing.html">routing guide</a>。</p><p>
你可以提供多个回调函数，它们的行为和中间件一样，除了这些回调可以通过调用<strong>next(&#39;router&#39;)</strong>来绕过剩余的路由回调。你可以使用这个机制来为一个路由设置一些前提条件，如果请求没能满足当前路由的处理条件，那么传递控制到随后的路由。</p>
<pre>
app.put('/', function(req, res) {
    res.send('PUT request to homepage');
});
</pre>

<h4 id="toc_23">app.render(view, [locals], callback)</h4>

<p>通过<strong>callback</strong>回调返回一个<strong>view</strong>渲染之后得到的HTML文本。它可以接受一个可选的参数，可选参数包含了这个<strong>view</strong>需要用到的本地数据。这个方法类似于<strong>res.render()</strong>，<strong>除了它不能把渲染得到的HTML文本发送给客户端</strong>。</p>

<blockquote>
<p>将<strong>app.render()</strong>当作是可以生成渲染视图字符串的工具方法。在<strong>res.render()</strong>内部，就是使用的<strong>app.render()</strong>来渲染视图。</p>

<p>如果使能了视图缓存，那么本地变量缓存就会保留。如果你想在开发的过程中缓存视图，设置它为<strong>true</strong>。在生产环境中，视图缓存默认是打开的。</p>
</blockquote>
<pre>
app.render('email', function(err, html) {
// ...
});
app.render('email', {name:'Tobi'}, function(err, html) {
// ...
});
</pre>
<h4 id="toc_24">app.route(path)</h4>

<p>返回一个单例模式的路由的实例，之后你可以在其上施加各种HTTP动作的中间件。使用<strong>app.route()</strong>来避免重复路由名字(例如错字错误)--说的意思应该是使用<strong>app.router()</strong>这个单例方法来避免同一个路径多个路由实例。</p>
<pre>
var app = express();
app.route('/events')
.all(function(req, res, next) {
  // runs for all HTTP verbs first
  // think of it as route specific middleware!
})
.get(function(req, res, next) {
  res.json(...);
})
.post(function(req, res, next) {
  // maybe add a new event...
})
</pre>

<h4>app.set(name, value)</h4><p>
给 name 设置项赋 value 值，name 是 <a target="_blank" href="#app.settings.table">Application settings</a> 中属性的一项。
对于一个类型是布尔型的属性调用app.set(&#39;foo&#39;, ture)等价于调用app.enable(&#39;foo&#39;)。同样的，调用app.set(&#39;foo&#39;, false)等价于调用app.disable(&#39;foo&#39;)。</p><p>
可以使用app.get()来取得设置的值：</p>
<pre>app.set('title', 'My Site');
    app.get('title'); // 'My Site'</pre>
<p id="app.settings.table"><strong>Application Settings</strong></p><p>
如果<strong>name</strong>是程序设置之一，它将影响到程序的行为。下边列出了程序中的设置。</p>

<table class="reference">
<thead>
<tr>
<th style="text-align: center">属性</th>
<th style="text-align: center">类型</th>
<th style="text-align: center">值</th>
<th style="text-align: center">默认</th>
</tr>
</thead>

<tbody>
<tr>
<td style="text-align: center">case sensitive routing</td>
<td style="text-align: center">Boolean</td>
<td style="text-align: center">启用区分大小写。</td>
<td style="text-align: center">不启用。对<strong>/Foo</strong>和<strong>/foo</strong>处理是一样。</td>
</tr>
<tr>
<td style="text-align: center">env</td>
<td style="text-align: center">String</td>
<td style="text-align: center">环境模型。</td>
<td style="text-align: center">process.env.NODE<em>ENV(NODE</em>ENV环境变量)或者&quot;development&quot;</td>
</tr>
<tr>
<td style="text-align: center">etag</td>
<td style="text-align: center">Varied</td>
<td style="text-align: center">设置<strong>ETag</strong>响应头。可取的值，可以查阅<a href="#etag.options.table">etag options table</a>。更多关于<a target="_blank" href="http://en.wikipedia.org/wiki/HTTP_ETag">HTTP ETag header</a>。</td>
<td style="text-align: center">weak</td>
</tr>
<tr>
<td style="text-align: center">jsonp callback name</td>
<td style="text-align: center">String</td>
<td style="text-align: center">指定默认JSONP回调的名称。</td>
<td style="text-align: center">?callback=</td>
</tr>
<tr>
<td style="text-align: center">json replacer</td>
<td style="text-align: center">String</td>
<td style="text-align: center">JSON替代品回调</td>
<td style="text-align: center">null</td>
</tr>
<tr>
<td style="text-align: center">json spaces</td>
<td style="text-align: center">Number</td>
<td style="text-align: center">当设置了这个值后，发送缩进空格美化过的JSON字符串。</td>
<td style="text-align: center">Disabled</td>
</tr>
<tr>
<td style="text-align: center">query parser</td>
<td style="text-align: center">Varied</td>
<td style="text-align: center">设置值为<strong>false</strong>来禁用<strong>query parser</strong>，或者设置<strong>simple</strong>,<strong>extended</strong>，也可以自己实现<strong>query string</strong>解析函数。<strong>simple</strong>基于<strong>Node</strong>原生的<strong>query</strong>解析，<a target="_blank" href="http://nodejs.org/api/querystring.html">querystring</a>。</td>
<td style="text-align: center">&quot;extend&quot;</td>
</tr>
<tr>
<td style="text-align: center">strict routing</td>
<td style="text-align: center">Boolean</td>
<td style="text-align: center">启用严格的路由。</td>
<td style="text-align: center">不启用。对<strong>/foo</strong>和<strong>/foo/</strong>的路由处理是一样。</td>
</tr>
<tr>
<td style="text-align: center">subdomain offset</td>
<td style="text-align: center">Number</td>
<td style="text-align: center">用来删除访问子域的主机点分部分的个数</td>
<td style="text-align: center">2</td>
</tr>
<tr>
<td style="text-align: center">trust proxy</td>
<td style="text-align: center">Varied</td>
<td style="text-align: center">指示<strong>app</strong>在一个反向代理的后面，使用<strong>x-Forwarded-*</strong>来确定连接和客户端的IP地址。注意:<strong>X-Forwarded-*</strong>头部很容易被欺骗，所有检测客户端的IP地址是靠不住的。<strong>trust proxy</strong>默认不启用。当启用时，Express尝试通过前端代理或者一系列代理来获取已连接的客户端IP地址。<strong>req.ips</strong>属性包含了已连接客户端IP地址的一个数组。为了启动它，需要设置在下面<a href="#trust.proxy.options.table">trust proxy options table</a>中定义的值。<strong>trust proxy</strong>的设置实现使用了<strong>proxy-addr</strong>包。如果想获得更多的信息，可以查阅它的文档</td>
<td style="text-align: center">Disable</td>
</tr>
<tr>
<td style="text-align: center">views</td>
<td style="text-align: center">String or Array</td>
<td style="text-align: center"><strong>view</strong>所在的目录或者目录数组。如果是一个数组，将按在数组中的顺序来查找<strong>view</strong>。</td>
<td style="text-align: center">process.cwd() + &#39;/views&#39;</td>
</tr>
<tr>
<td style="text-align: center">view cache</td>
<td style="text-align: center">Boolean</td>
<td style="text-align: center">启用视图模板编译缓存。</td>
<td style="text-align: center">在生成环境默认开启。</td>
</tr>
<tr>
<td style="text-align: center">view engine</td>
<td style="text-align: center">String</td>
<td style="text-align: center">省略时，默认的引擎被扩展使用。</td>
<td style="text-align: center"></td>
</tr>
<tr>
<td style="text-align: center">x-powered-by</td>
<td style="text-align: center">Boolean</td>
<td style="text-align: center">启用<strong>X-Powered-By:Express</strong>HTTP头部</td>
<td style="text-align: center">true</td>
</tr>
</tbody>
</table>

<p id="trust.proxy.options.table"><strong><strong>trust proxy</strong> 选项设置</strong>
查阅<a target="_blank" href="http://expressjs.com/guide/behind-proxies.html">Express behind proxies</a>来获取更多信息。</p>

<table class="reference">
<thead><tr><th>Type</th><th>Value</th></tr></thead>
<tbody>
<tr>
<td>Boolean</td>
<td>
<p>如果为<strong>true</strong>，客户端的IP地址作为<strong>X-Forwarded-*</strong>头部的最左边的条目。如果为<strong>false</strong>，可以理解为<strong>app</strong>直接与英特网直连，客户端的IP地址衍生自<strong>req.connection.remoteAddress</strong>。<strong>false</strong>是默认设置。</p>
</td>
</tr>
<tr>
<td>IP addresses</td>
<td>
<p>一个IP地址，子网，或者一组IP地址，和委托子网。下面列出的是一个预先配置的子网名列表。</p>
<ul>
<li>loopback - <strong>127.0.0.1/8</strong>, <strong>::1/128</strong></li>
<li>linklocal - <strong>169.254.0.0/16</strong>, <strong>fe80::/10</strong></li>
<li>uniquelocal - <strong>10.0.0.0/8</strong>, <strong>172.16.0.0/12</strong>, <strong>192.168.0.0/16</strong>, <strong>fc00::/7</strong></li>
</ul>
<p>使用下面方法中的任何一种来设置IP地址:</p>
<pre>
app.set('trust proxy', 'loopback') // specify a single subnet
app.set('trust proxy', 'loopback, 123.123.123.123') // specify a subnet and an address
app.set('trust proxy', 'loopback, linklocal, uniquelocal') // specify multiple subnets as CSV
app.set('trust proxy', ['loopback', 'linklocal', 'uniquelocal']) // specify multiple subnets as an array
</pre>
<p>当指定IP地址之后, 这个IP地址或子网会被设置了这个IP地址或子网的app排除在外, 最靠近程序服务的没有委托的地址将被看做客户端IP地址。</p>
</td>
</tr>
<tr>
<td>Number</td>
<td>
<p>信任从反向代理到app中间小于等于n跳的连接为客户端。</p>
</td>
</tr>
<tr>
<td>Function</td>
<td>
<p>客户自定义委托代理信任机制。如果你使用这个，请确保你自己知道你在干什么。</p>
<pre>
app.set('trust proxy', function (ip) {
    if (ip === '127.0.0.1' || ip === '123.123.123.123') return true; // trusted IPs
    else return false;
  })
</pre>
</td>
</tr>
</tbody>
</table>

<p id="etag.options.table"><strong><strong>etag</strong> 设置选项</strong>
<strong>ETag</strong>功能的实现使用了<a target="_blank" href="https://www.npmjs.org/package/etag">etag</a>包。如果你需要获得更多的信息，你可以查阅它的文档。</p>

<table class="reference">
<thead><tr><th>Type</th><th>Value</th></tr></thead>
<tbody>
<tr>
<td>Boolean</td>
<td>
<p>设置为<strong>true</strong>，启用weak ETag。这个是默认设置。设置<strong>false</strong>，禁用所有的ETag。<br>
</td>
</tr>
<tr>
<td>String</td>
<td>
如果是<strong>strong</strong>，使能strong ETag。如果是<strong>weak</strong>，启用<strong>weak</strong> ETag。
</td>
</tr>
<tr>
<td>Function</td>
<td>
<p>客户自定义ETag方法的实现. 如果你使用这个，请确保你自己知道你在干什么。</p>
<pre>
app.set('etag', function (body, encoding) {
  return generateHash(body, encoding); // consider the function is defined
  })
</pre>
</td>
</tr>
</tbody>
</table>

<h4 id="toc_25">app.use([path,], function [, function...])</h4>

<p>挂载<a target="_blank" href="http://expressjs.com/guide/using-middleware.html">中间件</a>方法到路径上。如果路径未指定，那么默认为&quot;/&quot;。</p>

<blockquote>
<p>一个路由将匹配任何路径如果这个路径以这个路由设置路径后紧跟着&quot;/&quot;。比如：<strong>app.use(&#39;/appale&#39;, ...)</strong>将匹配&quot;/apple&quot;，&quot;/apple/images&quot;，&quot;/apple/images/news&quot;等。</p>

<p>中间件中的<strong>req.originalUrl</strong>是<strong>req.baseUrl</strong>和<strong>req.path</strong>的组合，如下面的例子所示。
</p>
<pre>
app.use('/admin', function(req, res, next) {
// GET 'http://www.example.com/admin/new'
console.log(req.originalUrl); // '/admin/new'
console.log(req.baseUrl); // '/admin'
console.log(req.path);// '/new'
});
</pre>
</blockquote>

<p>在一个路径上挂载一个中间件之后，每当请求的路径的前缀部分匹配了这个路由路径，那么这个中间件就会被执行。
由于默认的路径为<strong>/</strong>，中间件挂载没有指定路径，那么对于每个请求，这个中间件都会被执行。
</p>
<pre>
 // this middleware will be executed for every request to the app.
app.use(function(req, res, next) {
    console.log('Time: %d', Date.now());
    next();
});
</pre><p>
中间件方法是顺序处理的，所以中间件包含的顺序是很重要的。</p>
<pre>
// this middleware will not allow the request to  go beyond it
app.use(function(req, res, next) {
    res.send('Hello World');
});
// this middleware will never reach this route
app.use('/', function(req, res) {
    res.send('Welcome');
});
</pre>

<p>路径可以是代表路径的一串字符，一个路径模式，一个匹配路径的正则表达式，或者他们的一组集合。
</p>
<p>下面是路径的简单的例子。</p>
<table class="reference">

  <thead>
    <tr>
      <th> 类型 </th>
      <th> 实例 </th>
    </tr>
  </thead>
  <tbody>

    <tr>
      <td>Path</td>
      <td>
        <pre>// will match paths starting with /abcd
app.use('/abcd', function (req, res, next) {
  next();
})</pre>
      </td>
    </tr>

    <tr>
      <td>Path Pattern</td>
      <td>
        <pre>// will match paths starting with /abcd and /abd
app.use('/abc?d', function (req, res, next) {
  next();
})

// will match paths starting with /abcd, /abbcd, /abbbbbcd and so on
app.use('/ab+cd', function (req, res, next) {
  next();
})

// will match paths starting with /abcd, /abxcd, /abFOOcd, /abbArcd and so on
app.use('/ab\*cd', function (req, res, next) {
  next();
})

// will match paths starting with /ad and /abcd
app.use('/a(bc)?d', function (req, res, next) {
  next();
})</pre>
      </td>
    </tr>

    <tr>
      <td>Regular Expression</td>
      <td>
        <pre>// will match paths starting with /abc and /xyz
app.use(/\/abc|\/xyz/, function (req, res, next) {
  next();
})</pre>
      </td>
    </tr>

    <tr>
      <td>Array</td>
      <td>
        <pre>// will match paths starting with /abcd, /xyza, /lmn, and /pqr
app.use(['/abcd', '/xyza', /\/lmn|\/pqr/], function (req, res, next) {
  next();
})</pre>
      </td>
    </tr>

  </tbody>

</table>

<p>方法可以是一个中间件方法，一系列中间件方法，一组中间件方法或者他们的集合。由于router和app实现了中间件接口，你可以像使用其他任一中间件方法那样使用它们。</p>

    <table class="reference">

  <thead>
    <tr>
      <th>用法</th>
      <th>实例</th>
    </tr>
  </thead>
  <tbody>

    <tr>
      <td>单个中间件</td>
      <td>你可以局部定义和挂载一个中间件。

<pre>app.use(function (req, res, next) {
  next();
})
</pre>
一个router是有效的中间件。

<pre>var router = express.Router();
router.get('/', function (req, res, next) {
  next();
})
app.use(router);
</pre>

一个Express程序是一个有效的中间件。
<pre>var subApp = express();
subApp.get('/', function (req, res, next) {
  next();
})
app.use(subApp);
</pre>
      </td>
    </tr>

    <tr>
      <td>一系列中间件</td>
      <td>
        对于一个相同的挂载路径，你可以挂载超过一个的中间件。
<pre>var r1 = express.Router();
r1.get('/', function (req, res, next) {
  next();
})

var r2 = express.Router();
r2.get('/', function (req, res, next) {
  next();
})

app.use(r1, r2);
</pre>
      </td>
    </tr>

    <tr>
      <td>Array</td>
      <td>
    在逻辑上使用一个数组来组织一组中间件。如果你传递一组中间件作为第一个或者唯一的参数，接着你需要指定挂载的路径。
<pre>var r1 = express.Router();
r1.get('/', function (req, res, next) {
  next();
})

var r2 = express.Router();
r2.get('/', function (req, res, next) {
  next();
})

app.use('/', [r1, r2]);
</pre>
      </td>
    </tr>

    <tr>
      <td>Combination</td>
      <td>
      你可以组合下面的所有方法来挂载中间件。
<pre>function mw1(req, res, next) { next(); }
function mw2(req, res, next) { next(); }

var r1 = express.Router();
r1.get('/', function (req, res, next) { next(); });

var r2 = express.Router();
r2.get('/', function (req, res, next) { next(); });

var subApp = express();
subApp.get('/', function (req, res, next) { next(); });

app.use(mw1, [mw2, r1, r2], subApp);
</pre>
      </td>
    </tr>

  </tbody>

</table>

<p>
下面是一些例子，在Express程序中使用express.static中间件。</p><p>
为程序托管位于程序目录下的public目录下的静态资源：</p>
<pre>
// GET /style.css etc
app.use(express.static(__dirname + '/public'));
</pre>
<p>在<strong>/static</strong>路径下挂载中间件来提供静态资源托管服务，只当请求是以<strong>/static</strong>为前缀的时候。</p>
<pre>
// GET /static/style.css etc.
app.use('/static', express.static(express.__dirname + '/public'));
</pre><p>
通过在设置静态资源中间件之后加载日志中间件来关闭静态资源请求的日志。</p>
<pre>
app.use(express.static(__dirname + '/public'));
app.use(logger());
</pre><p>
托管静态资源从不同的路径，但<strong>./public</strong>路径比其他更容易被匹配：
</p>
<pre>
app.use(express.static(__dirname + '/public'));
app.use(express.static(__dirname + '/files'));
app.use(express.static(__dirname + '/uploads'));
</pre>

<h2 id="toc_26">Request</h2>

<p><strong>req</strong>对象代表了一个HTTP请求，其具有一些属性来保存请求中的一些数据，比如<strong>query string</strong>，<strong>parameters</strong>，<strong>body</strong>，<strong>HTTP headers</strong>等等。在本文档中，按照惯例，这个对象总是简称为<strong>req</strong>(http响应简称为<strong>res</strong>)，但是它们实际的名字由这个回调方法在那里使用时的参数决定。
如下例子:</p>
<pre>
app.get('/user/:id', function(req, res) {
    res.send('user' + req.params.id);
});
</pre>
<p>其实你也可以这样写：</p>
<pre>
app.get('/user/:id', function(request, response) {
    response.send('user' + request.params.id);
});
</pre>

<h3 id="toc_27">Properties</h3>

<p>在<strong>Express 4</strong>中，<strong>req.files</strong>默认在<strong>req</strong>对象中不再是可用的。为了通过<strong>req.files</strong>对象来获得上传的文件，你可以使用一个<strong>multipart-handling</strong>(多种处理的工具集)中间件，比如<strong>busboy</strong>，<strong>multer</strong>，<strong>formidable</strong>，<strong>multipraty</strong>，<strong>connect-multiparty</strong>或者<strong>pez</strong>。</p>

<h4 id="toc_28">req.app</h4>

<p>这个属性持有<strong>express</strong>程序实例的一个引用，其可以作为中间件使用。</p><p>
如果你按照这个模式，你创建一个模块导出一个中间件，这个中间件只在你的主文件中<strong>require()</strong>它，那么这个中间件可以通过<strong>req.app</strong>来获取express的实例。
例如:</p>
<pre>
// index.js
app.get("/viewdirectory", require('./mymiddleware.js'));
</pre>
<pre>// mymiddleware.js
module.exports = function(req, res) {
    res.send('The views directory is ' + req.app.get('views'));
};</pre>

<h4 id="toc_29">req.baseUrl</h4>

<p>一个路由实例挂载的Url路径。</p>
<pre>
var greet = express.Router();
greet.get('/jp', function(req, res) {
    console.log(req.baseUrl); // greet
    res.send('Konichiwa!');
});
app.use('/greet', greet);
</pre><p>
即使你使用的路径模式或者一系列路径模式来加载路由，<strong>baseUrl</strong>属性返回匹配的字符串，而不是路由模式。下面的例子，<strong>greet</strong>路由被加载在两个路径模式上。</p>
<pre>
app.use(['/gre+t', 'hel{2}o'], greet); // load the on router on '/gre+t' and '/hel{2}o'
</pre><p>
当一个请求路径是<strong>/greet/jp</strong>，<strong>baseUrl</strong>是<strong>/greet</strong>，当一个请求路径是<strong>/hello/jp</strong>，<strong>req.baseUrl</strong>是<strong>/hello</strong>。
<strong>req.baseUrl</strong>和<strong>app</strong>对象的<a href="#toc_7">mountpath</a>属性相似，除了<strong>app.mountpath</strong>返回的是路径匹配模式。</p>

<h4 id="toc_30">req.body</h4>

<p>在请求的body中保存的是提交的一对对键值数据。默认情况下，它是<strong>undefined</strong>，当你使用比如<strong>body-parser</strong>和<strong>multer</strong>这类解析<strong>body</strong>数据的中间件时，它是填充的。
下面的例子，给你展示了怎么使用<strong>body-parser</strong>中间件来填充<strong>req.body</strong>。
</p>
<pre>
var app = require('express');
var bodyParser = require('body-parser');
var multer = require('multer')；// v1.0.5
var upload = multer(); // for parsing multipart/form-data
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({extended:true})); // for parsing application/x-www-form-urlencoded
app.post('/profile', upload.array(), function(req, res, next) {
    console.log(req.body);
    res.json(req.body);
});
</pre>
<h4>req.cookies</h4><p>
当使用cookie-parser中间件的时候，这个属性是一个对象，其包含了请求发送过来的cookies。如果请求没有带cookies，那么其值为{}。
</p>
<pre>
// Cookie: name=tj
req.cookies.name
// =&gt; "tj"
</pre>
<p>获取更多信息，问题，或者关注，可以查阅<a target="_blank" href="https://github.com/expressjs/cookie-parser">cookie-parser</a>。</p>

<h4 id="toc_31">req.fresh</h4>

<p>指示这个请求是否是新鲜的。其和<strong>req.stale</strong>是相反的。
当<strong>cache-control</strong>请求头没有<strong>no-cache</strong>指示和下面中的任一一个条件为<strong>true</strong>，那么其就为<strong>true</strong>：</p>

<ul>
<li><strong>if-modified-since</strong>请求头被指定，和<strong>last-modified</strong>请求头等于或者早于<strong>modified</strong>响应头。</li>
<li><strong>if-none-match</strong>请求头是<strong>*</strong>。</li>
<li><strong>if-none-match</strong>请求头在被解析进它的指令之后，和<strong>etag</strong>响应头的值不相等</li>
</ul>

<blockquote>
<p>ps:If-None-Match作用: If-None-Match和ETag一起工作，工作原理是在HTTP Response中添加ETag信息。 当用户再次请求该资源时，将在HTTP Request 中加入If-None-Match信息(ETag的值)。如果服务器验证资源的ETag没有改变（该资源没有更新），将返回一个304状态告诉客户端使用本地缓存文件。否则将返回200状态和新的资源和Etag.  使用这样的机制将提高网站的性能</p>
</blockquote>
<pre>
req.fresh
// =&gt; true
</pre>

<h4 id="toc_32">req.hostname</h4>

<p>包含了源自<strong>Host</strong>HTTP头部的<strong>hostname</strong>。</p><p>
当<strong>trust proxy</strong>设置项被设置为启用值，<strong>X-Forwarded-Host</strong>头部被使用来代替<strong>Host</strong>。这个头部可以被客户端或者代理设置。
<pre>
// Host: "example.com"
req.hostname
// =&gt; "example.com"
</pre>
<h4 id="toc_33">req.ips</h4>

<p>当<strong>trust proxy</strong>设置项被设置为启用值，这个属性包含了一组在<strong>X-Forwarded-For</strong>请求头中指定的IP地址。不然，其就包含一个空的数组。这个头部可以被客户端或者代理设置。</p><p>
例如，如果<strong>X-Forwarded-For</strong>是<strong>client</strong>，<strong>proxy1</strong>，<strong>proxy2</strong>，<strong>req.ips</strong>就是<strong>[&quot;clinet&quot;, &quot;proxy1&quot;, &quot;proxy2&quot;]</strong>，这里<strong>proxy2</strong>就是最远的下游。</p>

<h4 id="toc_34">req.originalUrl</h4>

<blockquote>
<p><strong>req.url</strong>不是一个原生的<strong>Express</strong>属性，它继承自<a target="_blank" href="https://nodejs.org/api/http.html#http_message_url">Node&#39;s http module</a>。</p>
</blockquote>

<p>这个属性很像<strong>req.url</strong>；然而，其保留了原版的请求链接，允许你自由地重定向<strong>req.url</strong>到内部路由。比如，<strong>app.use()</strong>的<strong>mounting</strong>特点可以重定向<strong>req.url</strong>跳转到挂载点。
</p>
<pre>
// GET /search?q=something
req.originalUrl
// =&gt; "/search?q=something"
</pre>

<h4 id="toc_35">req.params</h4>

<p>一个对象，其包含了一系列的属性，这些属性和在路由中命名的参数名是一一对应的。例如，如果你有<strong>/user/:name</strong>路由，<strong>name</strong>属性可作为<strong>req.params.name</strong>。这个对象默认值为<strong>{}</strong>。
</p>
<pre>
// GET /user/tj
req.params.name
// =&gt; "tj"
</pre><p>
当你使用正则表达式来定义路由规则，捕获组的组合一般使用<strong>req.params[n]</strong>，这里的<strong>n</strong>是第几个捕获租。这个规则被施加在无名通配符匹配，比如<strong>/file/*</strong>的路由：</p>
<pre>
// GET /file/javascripts/jquery.js
req.params[0]
// =&gt; "javascripts/jquery.js"
</pre>

<h4 id="toc_36">req.path</h4>

<p>包含请求URL的部分路径。</p>
<pre>
// example.com/users?sort=desc
req.path
// =&gt; "/users"
</pre>
<blockquote>
<p>当在一个中间件中被调用，挂载点不包含在<strong>req.path</strong>中。你可以查阅<a target="_blank" href="#toc_25">app.use()</a>获得跟多的信息。</p>
</blockquote>

<h4 id="toc_37">req.protocol</h4>

<p>请求的协议，一般为<strong>http</strong>，当启用TLS加密，则为<strong>https</strong>。</p><p>
当<strong>trust proxy</strong>设置一个启用的参数，如果存在<strong>X-Forwarded-Proto</strong>头部的话，其将被信赖和使用。这个头部可以被客户端或者代理设置。</p>
<pre>
req.ptotocol
// =&gt; "http"
</pre>

<h4 id="toc_38">req.query</h4>

<p>一个对象，为每一个路由中的<strong>query string</strong>参数都分配一个属性。如果没有<strong>query string</strong>，它就是一个空对象，<strong>{}</strong>。</p>
<pre>
// GET /search?q=tobi+ferret
req.query.q
// =&gt; "tobi ferret"
// GET /shoes?order=desc&amp;shoe[color]=blue&amp;shoe[type]=converse
req.query.order
// =&gt; "desc"
req.query.shoe.color
// =&gt; "blue"
req.query.shoe.type
// =&gt; "converse"
</pre>

<h4 id="toc_39">req.route</h4>

<p>当前匹配的路由，其为一串字符。比如：</p>
<pre>
app.get('/user/:id?', function userIdHandler(req, res) {
    console.log(req.route);
    res.send('GET')
})
</pre><p>
前面片段的输出为:</p>
<pre>
{ path:"/user/:id?"
    stack:
    [
        { handle:[Function:userIdHandler],
          name:"userIdHandler",
          params:undefined,
          path:undefined,
          keys:[],
          regexp:/^\/?$/i,
          method:'get'
        }
    ]
    methods:{get:true}
}
</pre>

<h4 id="toc_40">req.secure</h4>

<p>一个布尔值，如果建立的是TLS的连接，那么就为<strong>true</strong>。等价于：</p>
<pre>
'https' == req.protocol;</pre>

<h4 id="toc_41">req.signedCookies</h4>

<p>当使用<strong>cookie-parser</strong>中间件的时候，这个属性包含的是请求发过来的签名<strong>cookies</strong>，这个属性取得的是不含签名，可以直接使用的值。签名的<strong>cookies</strong>保存在不同的对象中来体现开发者的意图；不然，一个恶意攻击可以被施加在<strong>req.cookie</strong>值上(它是很容易被欺骗的)。记住，签名一个<strong>cookie</strong>不是把它藏起来或者加密；而是简单的防止篡改(因为签名使用的加密是私人的)。如果没有发送签名的<strong>cookie</strong>，那么这个属性默认为<strong>{}</strong>。</p>

<pre>
// Cookie： user=tobi.CP7AWaXDfAKIRfH49dQzKJx7sKzzSoPq7/AcBBRVwlI3
req.signedCookies.user
// =&gt; "tobi"
</pre>

<p>为了获取更多的信息，问题或者关注，可以参阅<a target="_blank" href="https://github.com/expressjs/cookie-parser">cookie-parser</a>。</p>

<h4 id="toc_42">req.stale</h4>

<p>指示这个请求是否是<strong>stale</strong>(陈旧的)，它与<strong>req.fresh</strong>是相反的。更多信息，可以查看<a href="#toc_31">req.fresh</a>。</p>
<pre>
req.stale
// =&gt; true
</pre>

<h4 id="toc_43">req.subdomains</h4>

<p>请求中域名的子域名数组。</p>
<pre>
// Host: "tobi.ferrets.example.com"
req.subdomains
// =&gt; ["ferrets", "tobi"]
</pre>

<h4 id="toc_44">req.xhr</h4>

<p>一个布尔值，如果<strong>X-Requested-With</strong>的值为<strong>XMLHttpRequest</strong>，那么其为<strong>true</strong>，其指示这个请求是被一个客服端库发送，比如<strong>jQuery</strong>。
</p>
<pre>
req.xhr
// =&gt; true
</pre>
<h3>Methods</h3>
<h4 id="res.accepts">req.accepts(types)</h4><p>
检查这个指定的内容类型是否被接受，基于请求的Accept HTTP头部。这个方法返回最佳匹配，如果没有一个匹配，那么其返回undefined(在这个case下，服务器端应该返回406和&quot;Not Acceptable&quot;)。</p><p>
type值可以是一个单的MIME type字符串(比如application/json)，一个扩展名比如json，一个逗号分隔的列表，或者一个数组。对于一个列表或者数组，这个方法返回最佳项(如果有的话)。</p>
<pre>
// Accept: text/html
req.accepts('html');
// =&gt; "html"
// Accept: text/*, application/json
req.accepts('html');
// =&gt; "html"
req.accepts('text/html');
// =&gt; "text/html"
req.accepts(['json', 'text']);
// =&gt; "json"
req.accepts('application/json');
// =&gt; "application/json"
// Accept: text/*, application/json
req.accepts('image/png');
req.accepts('png');
// =&gt; undefined
// Accept: text/*;q=.5, application/json
req.accepts(['html', 'json']);
// =&gt; "json"
</pre>
<p>获取更多信息，或者如果你有问题或关注，可以参阅<a target="_blank" href="https://github.com/expressjs/accepts">accepts</a>。</p>

<h4 id="toc_45">req.acceptsCharsets(charset[, ...])</h4>

<p>返回指定的字符集集合中第一个的配置的字符集，基于请求的<strong>Accept-Charset</strong>HTTP头。如果指定的字符集没有匹配的，那么就返回false。
获取更多信息，或者如果你有问题或关注，可以参阅<a target="_blank" href="https://github.com/expressjs/accepts">accepts</a>。</p>

<h4 id="toc_46">req.acceptsEncodings(encoding[, ...])</h4>

<p>返回指定的编码集合中第一个的配置的编码，基于请求的<strong>Accept-Encoding</strong>HTTP头。如果指定的编码集没有匹配的，那么就返回false。
获取更多信息，或者如果你有问题或关注，可以参阅<a target="_blank" href="https://github.com/expressjs/accepts">accepts</a>。</p>

<h4 id="toc_47">req.acceptsLanguages(lang [, ...])</h4>

<p>返回指定的语言集合中第一个的配置的语言，基于请求的<strong>Accept-Language</strong>HTTP头。如果指定的语言集没有匹配的，那么就返回false。
获取更多信息，或者如果你有问题或关注，可以参阅<a target="_blank" href="https://github.com/expressjs/accepts">accepts</a>。</p>

<h4 id="toc_48">req.get(field)</h4>

<p>返回指定的请求HTTP头部的域内容(不区分大小写)。<strong>Referrer</strong>和<strong>Referer</strong>的域内容可互换。
<pre>
req.get('Content-type');
// =&gt; "text/plain"
req.get('content-type');
// =&gt; "text/plain"
req.get('Something')
// =&gt; undefined
</pre><p>
其是</strong>req.header(field)的别名。</p>

<h4 id="toc_49">req.is(type)</h4>

<p>如果进来的请求的<strong>Content-type</strong>头部域匹配参数<strong>type</strong>给定的<strong>MIME type</strong>，那么其返回<strong>true</strong>。否则返回<strong>false</strong>。</p>
<pre>
// With Content-Type: text/html; charset=utf-8
req.is('html');
req.is('text/html');
req.is('text/*');
// =&gt; true
// When Content-Type is application/json
req.is('json');
req.is('application/json');
req.is('application/*');
// =&gt; true
req.is('html');
// =&gt; false
</pre><p>

获取更多信息，或者如果你有问题或关注，可以参阅<a target="_blank" href="https://github.com/expressjs/type-is">type-is</a>。</p>

<h4 id="toc_50">req.param(naem, [, defaultValue])</h4>

<blockquote>
<p>过时的。可以在适合的情况下，使用<strong>req.params</strong>，<strong>req.body</strong>或者<strong>req.query</strong>。</p>
</blockquote>

<p>返回当前参数<strong>name</strong>的值。
</p>
<pre>
// ?name=tobi
req.param('name')
// =&gt; "tobi"
// POST name=tobi
req.param('name')
// =&gt; "tobi"
// /user/tobi for /user/:name
req.param('name')
// =&gt; "tobi"
</pre><p>

按下面给出的顺序查找：</p>

<ul>
<li>req.params</li>
<li>req.body</li>
<li>req.query</li>
</ul>

<p>可选的，你可以指定一个<strong>defaultValue</strong>来设置一个默认值，如果这个参数在任何一个请求的对象中都不能找到。</p>

<blockquote>
<p>直接通过<strong>req.params</strong>，<strong>req.body</strong>，<strong>req.query</strong>取得应该更加的清晰-除非你确定每一个对象的输入。
<strong>Body-parser</strong>中间件必须加载，如果你使用<strong>req.param()</strong>。详细请看<a target="_blank" href="#toc_30">req.body</a>。</p>
</blockquote>

<h2 id="toc_51">Response</h2>

<p><strong>res</strong>对象代表了当一个HTTP请求到来时，<strong>Express</strong>程序返回的HTTP响应。在本文档中，按照惯例，这个对象总是简称为<strong>res</strong>(http请求简称为<strong>req</strong>)，但是它们实际的名字由这个回调方法在那里使用时的参数决定。
例如：</p><pre>
app.get('/user/:id', function(req, res) {
    res.send('user' + req.params.id);
});
</pre><p>
这样写也是一样的：
</p>
<pre>
app.get('/user/:id', function(request, response) {
    response.send('user' + request.params.id);
});
</pre>

<h3>Properties</h3>
<h4>res.app</h4><p>
这个属性持有express程序实例的一个引用，其可以在中间件中使用。</p><p>
res.app和请求对象中的req.app属性是相同的。/p>


<h4>res.headersSent</h4><p>
布尔类型的属性，指示这个响应是否已经发送HTTP头部。</p><pre>
app.get('/', function(req, res) {
    console.log(res.headersSent); // false
    res.send('OK'); // send之后就发送了头部
    console.log(res.headersSent); // true
});
</pre>
<h4 id="toc_52">res.locals</h4>

<p>一个对象，其包含了本次请求的响应中的变量和因此它的变量只提供给本次请求响应的周期内视图渲染里使用(如果有视图的话)。
其他方面，其和<strong>app.locals</strong>是一样的。</p><p>
这个参数在导出请求级别的信息是很有效的，这些信息比如请求路径，已认证的用户，用户设置等等。</p>
<pre>
app.use(function(req, res, next) {
    res.locals.user = req.user;
    res.locals.authenticated = !req.user.anonymous;
    next();
});
</pre>

<h3 id="toc_53">Methods</h3>

<h4 id="toc_54">res.append(field [, value])</h4>

<blockquote>
<p>res.append()方法在<strong>Expresxs</strong>4.11.0以上版本才支持。</p>
</blockquote>

<p>在指定的<strong>field</strong>的HTTP头部追加特殊的值<strong>value</strong>。如果这个头部没有被设置，那么将用<strong>value</strong>新建这个头部。<strong>value</strong>可以是一个字符串或者数组。</p><p>
注意：在<strong>res.append()</strong>之后调用<strong>app.set()</strong>函数将重置前面设置的值。</p>
<pre>
res.append('Lind', ['&lt;http://localhost&gt;', '&lt;http://localhost:3000&gt;']);
res.append('Set-Cookie', 'foo=bar;Path=/;HttpOnly');
res.append('Warning', '199 Miscellaneous warning');
</pre>

<h4 id="toc_55">res.attachment([filename])</h4>

<p>设置HTTP响应的<strong>Content-Disposition</strong>头内容为&quot;attachment&quot;。如果提供了<strong>filename</strong>，那么将通过<strong>res.type()</strong>获得扩展名来设置<strong>Content-Type</strong>，并且设置<strong>Content-Disposition</strong>内容为&quot;filename=&quot;parameter。
</p>
<pre>
res.attachment();
// Content-Disposition: attachment
res.attachment('path/to/logo.png');
// Content-Disposition: attachment; filename="logo.png"
// Content-Type: image/png
</pre>

<h4 id="toc_56">res.cookie(name, value [,options])</h4>

<p>设置<strong>name</strong>和<strong>value</strong>的<strong>cookie</strong>，<strong>value</strong>参数可以是一串字符或者是转化为json字符串的对象。</p><p>
options是一个对象，其可以有下列的属性。</p>

<table class="reference">
<thead>
<tr>
<th style="text-align: center">属性</th>
<th style="text-align: center">类型</th>
<th style="text-align: center">描述</th>
</tr>
</thead>

<tbody>
<tr>
<td style="text-align: center">domain</td>
<td style="text-align: center">String</td>
<td style="text-align: center">设置cookie的域名。默认是你本app的域名。</td>
</tr>
<tr>
<td style="text-align: center">expires</td>
<td style="text-align: center">Date</td>
<td style="text-align: center">cookie的过期时间，GMT格式。如果没有指定或者设置为0，则产生新的cookie。</td>
</tr>
<tr>
<td style="text-align: center">httpOnly</td>
<td style="text-align: center">Boolean</td>
<td style="text-align: center">这个cookie只能被web服务器获取的标示。</td>
</tr>
<tr>
<td style="text-align: center">maxAge</td>
<td style="text-align: center">String</td>
<td style="text-align: center">是设置过去时间的方便选项，其为过期时间到当前时间的毫秒值。</td>
</tr>
<tr>
<td style="text-align: center">path</td>
<td style="text-align: center">String</td>
<td style="text-align: center">cookie的路径。默认值是<strong>/</strong>。</td>
</tr>
<tr>
<td style="text-align: center">secure</td>
<td style="text-align: center">Boolean</td>
<td style="text-align: center">标示这个cookie只用被<strong>HTTPS</strong>协议使用。</td>
</tr>
<tr>
<td style="text-align: center">signed</td>
<td style="text-align: center">Boolean</td>
<td style="text-align: center">指示这个cookie应该是签名的。</td>
</tr>
</tbody>
</table>

<blockquote>
<p>res.cookie()所作的都是基于提供的<strong>options</strong>参数来设置<strong>Set-Cookie</strong>头部。没有指定任何的<strong>options</strong>，那么默认值在<strong>RFC6265</strong>中指定。</p>
</blockquote>

<p>使用实例：
</p>
<pre>
res.cookie('name', 'tobi', {'domain':'.example.com', 'path':'/admin', 'secure':true});
res.cookie('remenberme', '1', {'expires':new Date(Date.now() + 90000), 'httpOnly':true});
</pre>
<p>maxAge 是一个方便设置过期时间的方便的选项，其以当前时间开始的毫秒数来计算。下面的示例和上面的第二条功效一样。</p>
<pre>res.cookie('rememberme', '1', {'maxAge':90000}, "httpOnly":true);</pre>
<p>你可以设置传递一个对象作为value的参数。然后其将被序列化为Json字符串，被bodyParser()中间件解析。</p>
<pre>
res.cookie('cart', {'items':[1, 2, 3]});
res.cookie('cart', {'items':[1, 2, 3]}, {'maxAge':90000});
</pre>
<p>当我们使用cookie-parser中间件的时候，这个方法也支持签名的cookie。简单地，在设置options时包含signed选项为true。然后res.cookie()将使用传递给cookieParser(secret)的密钥来签名这个值。</p>
<pre>res.cookie('name', 'tobi', {'signed':true});</pre>

<h4 id="toc_57">res.clearCookie(name [,options])</h4>

<p>根据指定的<strong>name</strong>清除对应的cookie。更多关于<strong>options</strong>对象可以查阅<strong>res.cookie()</strong>。</p>
<pre>
res.cookie('name', 'tobi', {'path':'/admin'});
res.clearCookie('name', {'path':'admin'});
</pre>

<h4 id="toc_58">res.download(path, [,filename], [,fn])</h4>

<p>传输<strong>path</strong>指定文件作为一个附件。通常，浏览器提示用户下载。默认情况下，<strong>Content-Disposition</strong>头部&quot;filename=&quot;的参数为<strong>path</strong>(通常会出现在浏览器的对话框中)。通过指定<strong>filename</strong>参数来覆盖默认值。</p><p>
当一个错误发生时或者传输完成，这个方法将调用<strong>fn</strong>指定的回调方法。这个方法使用<strong>res.sendFile()</strong>来传输文件。</p>
<pre>
res.download('/report-12345.pdf');
res.download('/report-12345.pdf', 'report.pdf');
res.download('report-12345.pdf', 'report.pdf', function(err) {
// Handle error, but keep in mind the response may be partially-sent
// so check res.headersSent
if (err) {
} else {
// decrement a download credit, etc.
}
});
</pre>

<h4 id="toc_59">res.end([data] [, encoding])</h4>

<p>结束本响应的过程。这个方法实际上来自<strong>Node</strong>核心模块，具体的是<a target="_blank" href="https://nodejs.org/api/http.html#http_response_end_data_encoding_callback">response.end() method of http.ServerResponse</a>。<p><p>
用来快速结束请求，没有任何的数据。如果你需要发送数据，可以使用<a href="#toc_67">res.send()</a>和<a target="_blank" href="#toc_62">res.json()</a>这类的方法。</p>
<pre>
res.end();
res.status(404).end();
</pre>

<h4 id="toc_60">res.format(object)</h4>

<p>进行内容协商，根据请求的对象中<strong>Accept</strong>HTTP头部指定的接受内容。它使用 req.accepts()来选择一个句柄来为请求服务，这些句柄按质量值进行排序。如果这个头部没有指定，那么第一个方法默认被调用。当不匹配时，服务器将返回<strong>406</strong>&quot;Not Acceptable&quot;，或者调用<strong>default</strong>回调。</p><p>
<strong>Content-Type</strong>请求头被设置，当一个回调方法被选择。然而你可以改变他，在这个方法中使用这些方法，比如<strong>res.set()</strong>或者<strong>res.type()</strong>。</p><p>
下面的例子，将回复<strong>{&quot;message&quot;:&quot;hey&quot;}</strong>，当请求的对象中<strong>Accept</strong>头部设置成&quot;application/json&quot;或者&quot;*/json&quot;(不过如果是<strong>*/*</strong>，然后这个回复就是&quot;hey&quot;)。</p>
<pre>
res.format({
    'text/plain':function() {
        res.send('hey');
    },
    'text/html':function() {
        res.send('&lt;p&gt;hey&lt;/p&gt;');
    },
    'application/json':function() {
        res.send({message:'hey'});
    },
    'default':function() {
        res.status(406).send('Not Acceptable');
    }
})
</pre><p>
除了规范化的MIME类型之外，你也可以使用拓展名来映射这些类型来避免冗长的实现：</p>
<pre>
res.format({
    text:function() {
        res.send('hey');
    },
    html:function() {
        res.send('&lt;p&gt;hey&lt;/p&gt;');
    },
    json:function() {
        res.send({message:'hey'});
    }
})
</pre>

<h4 id="toc_61">res.get(field)</h4>

<p>返回<strong>field</strong>指定的HTTP响应的头部。匹配是区分大小写。</p>
<pre>
res.get('Content-Type');
// =&gt; "text/plain"
</pre>
<h4 id="toc_62">res.json([body])</h4>

<p>发送一个json的响应。这个方法和将一个对象或者一个数组作为参数传递给<strong>res.send()</strong>方法的效果相同。不过，你可以使用这个方法来转换其他的值到json，例如<strong>null</strong>，<strong>undefined</strong>。(虽然这些都是技术上无效的JSON)。</p>
<pre>
res.json(null);
res.json({user:'tobi'});
res.status(500).json({error:'message'});
</pre>

<h4>res.jsonp([body])</h4><p>
发送一个json的响应，并且支持JSONP。这个方法和res.json()效果相同，除了其在选项中支持JSONP回调。
</p>
<pre>
res.jsonp(null)
// =&gt; null
res.jsonp({user:'tobi'})
// =&gt; {"user" : "tobi"}
res.status(500).jsonp({error:'message'})
// =&gt; {"error" : "message"}
</pre>
<p>
默认情况下，jsonp的回调方法简单写作callback。可以通过<a href="#app.settings.table">jsonp callback name</a>设置来重写它。</p><p>
下面是一些例子使用JSONP响应，使用相同的代码:</p>
<pre>
// ?callback=foo
res.jsonp({user:'tobo'})
// =&gt; foo({"user":"tobi"})
app.set('jsonp callback name', 'cb')
// ?cb=foo
res.status(500).jsonp({error:'message'})
// =&gt; foo({"error":"message"})
</pre>
<h4 id="toc_63">res.links(links)</h4>

<p>连接这些<strong>links</strong>，<strong>links</strong>是以传入参数的属性形式提供，连接之后的内容用来填充响应的Link HTTP头部。</p>
<pre>
res.links({
    next:'http://api.example.com/users?page=2',
    last:'http://api.example.com/user?page=5'
});
</pre>
<p>
效果：</p>
<pre>
Link:&lt;http://api.example.com/users?page=2&gt;;rel="next",
&lt;http://api.example.com/users?page=5&gt;;rel="last"
</pre>

<h4 id="toc_64">res.location(path)</h4>

<p>设置响应的<strong>Location</strong>HTTP头部为指定的<strong>path</strong>参数。
</p>
<pre>
res.location('/foo/bar');
res.location('http://example.com');
res.location('back');
</pre><p>
当<strong>path</strong>参数为<strong>back</strong>时，其具有特殊的意义，其指定URL为请求对象的<strong>Referer</strong>头部指定的URL。如果请求中没有指定，那么其即为&quot;/&quot;。</p>

<blockquote>
<p>Express传递指定的URL字符串作为回复给浏览器响应中的<strong>Location</strong>头部的值，不检测和操作，除了<strong>back</strong>这个参数。浏览器会将用户重定向到<strong>location</strong>设置的url或者<strong>Referer</strong>的url（<strong>back</strong>参数的情况）</p>
</blockquote>

<h4 id="toc_65">res.redirect([status,] path)</h4>

<p>重定向来源于指定<strong>path</strong>的URL，以及指定的<a target="_blank" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">HTTP status code</a><strong>status</strong>。如果你没有指定<strong>status</strong>，status code默认为&quot;302 Found&quot;。</p>
<pre>
res.redirect('/foo/bar');
res.redirect('http://example.com');
res.redirect(301, 'http://example.com');
res.redirect('../login');
</pre><p>
重定向也可以是完整的URL，来重定向到不同的站点。
</p>
<pre>res.redirect('http://google.com');&lt;/p&gt;&lt;p&gt;
重定向也可以相对于主机的根路径。比如，如果程序的路径为&lt;strong&gt;http://example.com/admin/post/new&lt;/strong&gt;，那么下面将重定向到&lt;strong&gt;http://example.com/admim&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;res.redirect('/admin');</pre><p>
重定向也可以相对于当前的URL。比如，来之于<strong>http://example.com/blog/admin/</strong>(注意结尾的<strong>/</strong>)，下面将重定向到<strong>http://example.com/blog/admin/post/new</strong>。</p><pre>res.redirect('post/new');</pre><p>
如果来至于<strong>http://example.com/blog/admin</strong>（没有尾部<strong>/</strong>），重定向<strong>post/new</strong>，将重定向到<strong>http://example.com/blog/post/new</strong>。如果你觉得上面很混乱，可以把路径段认为目录(有&#39;/&#39;)或者文件，这样是可以的。相对路径的重定向也是可以的。如果你当前的路径为<strong>http://example.com/admin/post/new</strong>，下面的操作将重定向到<strong>http://example.com/admin/post</strong>：</p>
<pre>res.redirect('..');</pre><p>
<strong>back</strong>将重定向请求到<a target="_blank" href="http://en.wikipedia.org/wiki/HTTP_referer">referer</a>，当没有<strong>referer</strong>的时候，默认为<strong>/</strong>。</p>
<pre>res.redirect('back');</pre>

<h4 id="toc_66">res.render(view [, locals] [, callback])</h4>

<p>渲染一个视图，然后将渲染得到的HTML文档发送给客户端。可选的参数为:</p>

<ul>
<li><strong>locals</strong>，定义了视图本地参数属性的一个对象。</li>
<li><strong>callback</strong>，一个回调方法。如果提供了这个参数，<strong>render</strong>方法将返回错误和渲染之后的模板，并且不自动发送响应。当有错误发生时，可以在这个回调内部，调用<strong>next(err)</strong>方法。</li>
</ul>

<blockquote>
<p>本地变量缓存使能视图缓存。在开发环境中缓存视图，需要手动设置为true；视图缓存在生产环境中默认开启。</p>
</blockquote>
<pre>
// send the rendered view to the client
res.render('index');
// if a callback is specified, the render HTML string has to be sent explicitly
res.render('index', function(err, html) {
    res.send(html);
});
// pass a local variable to  the view
res.render('user', {name:'Tobi'}, function(err, html) {
    // ...
});
</pre>

<h4 id="toc_67">res.send([body])</h4>

<p>发送HTTP响应。</p><p>
<strong>body</strong>参数可以是一个<strong>Buffer</strong>对象，一个字符串，一个对象，或者一个数组。比如：</p>
<pre>
res.send(new Buffer('whoop'));
res.send({some:'json'});
res.send('&lt;p&gt;some html&lt;/p&gt;');
res.status(404).send('Sorry, we cannot find that!');
res.status(500).send({ error: 'something blew up' });
</pre><p>对于一般的非流请求，这个方法可以执行许多有用的的任务：比如，它自动给Content-LengthHTTP响应头赋值(除非先前定义)，也支持自动的HEAD和HTTP缓存更新。</p><p>
当参数是一个Buffer对象，这个方法设置Content-Type响应头为application/octet-stream，除非事先提供，如下所示:</p>

<pre>
res.set('Content-Type', 'text/html');
res.send(new Buffer('&lt;p&gt;some html&lt;/p&gt;'));
</pre><p>
当参数是一个字符串，这个方法设置Content-Type响应头为text/html：</p>
<pre>res.send('&lt;p&gt;some html&lt;/p&gt;');</pre>

<p>当参数是一个对象或者数组，Express使用JSON格式来表示：</p>
<pre>res.send({user:'tobi'});
res.send([1, 2, 3]);</pre>

<h4 id="toc_68">res.sendFile(path [, options] [, fn])</h4>

<blockquote>
<p><strong>res.sendFile()</strong>从<strong>Express v4.8.0</strong>开始支持。</p>
</blockquote>

<p>传输<strong>path</strong>指定的文件。根据文件的扩展名设置<strong>Content-Type</strong>HTTP头部。除非在<strong>options</strong>中有关于<strong>root</strong>的设置，<strong>path</strong>一定是关于文件的绝对路径。
下面的表提供了<strong>options</strong>参数的细节:</p>

<table class="reference">
<thead>
<tr>
<th style="text-align: center">属性</th>
<th style="text-align: center">描述</th>
<th style="text-align: center">默认值</th>
<th style="text-align: center">可用版本</th>
</tr>
</thead>

<tbody>
<tr>
<td style="text-align: center">maxAge</td>
<td style="text-align: center">设置<strong>Cache-Control</strong>的<strong>max-age</strong>属性，格式为毫秒数，或者是<a target="_blank" href="https://www.npmjs.org/package/ms">ms format</a>的一串字符串</td>
<td style="text-align: center">0</td>
<td style="text-align: center"></td>
</tr>
<tr>
<td style="text-align: center">root</td>
<td style="text-align: center">相对文件名的根目录</td>
<td style="text-align: center"></td>
<td style="text-align: center"></td>
</tr>
<tr>
<td style="text-align: center">lastModified</td>
<td style="text-align: center">设置<strong>Last-Modified</strong>头部为此文件在系统中的最后一次修改时间。设置<strong>false</strong>来禁用它</td>
<td style="text-align: center">Enable</td>
<td style="text-align: center">4.9.0+</td>
</tr>
<tr>
<td style="text-align: center">headers</td>
<td style="text-align: center">一个对象，包含了文件相关的HTTP头部。</td>
<td style="text-align: center"></td>
<td style="text-align: center"></td>
</tr>
<tr>
<td style="text-align: center">dotfiles</td>
<td style="text-align: center">是否支持点开头文件名的选项。可选的值&quot;allow&quot;,&quot;deny&quot;,&quot;ignore&quot;</td>
<td style="text-align: center">&quot;ignore&quot;</td>
<td style="text-align: center">&nbsp;</td>
</tr>
</tbody>
</table>

<p>当传输完成或者发生了什么错误，这个方法调用<strong>fn</strong>回调方法。如果这个回调参数指定了和一个错误发生，回调方法必须明确地通过结束请求-响应循环或者传递控制到下个路由来处理响应过程。</p><p>
下面是使用了所有参数的使用<strong>res.sendFile()</strong>的例子：</p>
<pre>
app.get('/file/:name', function(req, res, next) {
    var options = {
        root:__dirname + '/public',
        dotfile:'deny',
        headers:{
            'x-timestamp':Date.now(),
            'x-sent':true
        }
    };
    var fileName = req.params.name;
    res.sendFile(fileName, options, function(err) {
        if (err) {
            console.log(err);
            res.status(err.status).end();
        }
        else {
            console.log('sent', fileName);
        }
    });
});
</pre>

<p>res.sendFile提供了文件服务的细粒度支持，如下例子说明：</p>
<pre>
app.get('/user/:uid/photos/:file', function(req, res) {
    var uid = req.params.uid
        , file = req.params.file;
    req.user.mayViewFilesFrom(uid, function(yes) {
        if (yes) {
            res.sendFile('/upload/' + uid + '/' + file);
        }
        else {
            res.status(403).send('Sorry! you cant see that.');
        }
    });
})
</pre>

<p>获取更多信息，或者你有问题或者关注，可以查阅<a target="_blank" href="https://github.com/pillarjs/send">send</a>。</p>

<h4 id="toc_69">res.sendStatus(statusCode)</h4>

<p>设置响应对象的<strong>HTTP status code</strong>为<strong>statusCode</strong>并且发送<strong>statusCode</strong>的相应的字符串形式作为响应的Body。</p>
<pre>
res.sendStatus(200); // equivalent to res.status(200).send('OK');
res.sendStatus(403); // equivalent to res.status(403).send('Forbidden');
res.sendStatus(404); // equivalent to res.status(404).send('Not Found');
res.sendStatus(500); // equivalent to res.status(500).send('Internal Server Error')
</pre><p>
如果一个不支持的状态被指定，这个HTTP status依然被设置为<strong>statusCode</strong>并且用这个code的字符串作为Body。</p>
<pre>res.sendStatus(2000); // equivalent to res.status(2000).send('2000');</pre><p>
<a target="_blank" href="http://en.wikipedia.org/wiki/List_of_HTTP_status_codes">More about HTTP Status Codes</a></p>
</p>
<h4 id="toc_70">res.set(field [, value])</h4>

<p>设置响应对象的HTTP头部<strong>field</strong>为<strong>value</strong>。为了一次设置多个值，那么可以传递一个对象为参数。</p>
<pre>
res.set('Content-Type', 'text/plain');
res.set({
    'Content-Type':'text/plain',
    'Content-Length':'123',
    'ETag':'123456'
})
</pre><p>
其和</strong>res.header(field [,value])效果一致。</p>

<h4 id="toc_71">res.status(code)</h4>

<p>使用这个方法来设置响应对象的HTTP status。其是Node中<a target="_blank" href="http://nodejs.org/api/http.html#http_response_statuscode">response.statusCode</a>的一个连贯性的别名。</p>
<pre>
res.status(403).end();
res.status(400).send('Bad Request');
res.status(404).sendFile('/absolute/path/to/404.png');
</pre>
<h4 id="toc_72">res.type(type)</h4>

<p>程序将设置<strong>Content-Type</strong>HTTP头部的MIME type，如果这个设置的<strong>type</strong>能够被<a target="_blank" href="https://github.com/broofa/node-mime">mime.lookup</a>解析成正确的<strong>Content-Type</strong>。如果<strong>type</strong>中包含了<strong>/</strong>字符，那么程序会直接设置<strong>Content-Type</strong>为<strong>type</strong>。</p>

<pre>
res.type('.html');              // =&gt; 'text/html'
res.type('html');               // =&gt; 'text/html'
res.type('json');               // =&gt; 'application/json'
res.type('application/json');   // =&gt; 'application/json'
res.type('png');                // =&gt; image/png:
</pre>
<h4 id="toc_73">res.vary(field)</h4>

<p>在没有Vary应答头部时增加Vary应答头部。</p>

<blockquote>
<p>ps：vary的意义在于告诉代理服务器/缓存/CDN，如何判断请求是否一样，vary中的组合就是服务器/缓存/CDN判断的依据，比如Vary中有User-Agent，那么即使相同的请求，如果用户使用IE打开了一个页面，再用Firefox打开这个页面的时候，CDN/代理会认为是不同的页面，如果Vary中没有User-Agent，那么CDN/代理会认为是相同的页面，直接给用户返回缓存的页面，而不会再去web服务器请求相应的页面。通俗的说就相当于<strong>field</strong>作为了一个缓存的key来判断是否命中缓存</p>
</blockquote>

<pre>res.vary('User-Agent').render('docs');</pre>
<h2 id="toc_74">Router</h2>
<blockquote>
<p>一个<strong>router</strong>对象是一个单独的实例关于中间件和路由。你可以认为其是一个&quot;mini-application&quot;（迷你程序），其具有操作中间件和路由方法的能力。每个<strong>Express</strong>程序有一个内建的app路由。
路由自身表现为一个中间件，所以你可以使用它作为<strong>app.use()</strong>方法的一个参数或者作为另一个路由的<strong>use()</strong>的参数。
顶层的<strong>express</strong>对象有一个<strong>Router()</strong>方法，你可以使用<strong>Router()</strong>来创建一个新的<strong>router</strong>对象。</p></blockquote>
<pre>res.vary('User-Agent').render('docs');</pre>
<h4 id="toc_75">Router([options])</h4>

<p>如下，可以创建一个路由：</p>
<pre>var router = express.Router([options]);</pre><p>
<strong>options</strong>参数可以指定路由的行为，其有下列选择：</p>

<table class="reference">
<thead>
<tr>
<th style="text-align: center">属性</th>
<th style="text-align: center">描述</th>
<th style="text-align: center">默认值</th>
<th style="text-align: center">可用性</th>
</tr>
</thead>

<tbody>
<tr>
<td style="text-align: center">caseSensitive</td>
<td style="text-align: center">是否区分大小写</td>
<td style="text-align: center">默认不启用。对待<strong>/Foo</strong>和<strong>/foo</strong>一样。</td>
<td style="text-align: center"></td>
</tr>
<tr>
<td style="text-align: center">mergeParams</td>
<td style="text-align: center">保存父路由的<strong>res.params</strong>。如果父路由参数和子路由参数冲突，子路由参数优先。</td>
<td style="text-align: center">false</td>
<td style="text-align: center">4.5.0+</td>
</tr>
<tr>
<td style="text-align: center">strict</td>
<td style="text-align: center">使能严格路由。</td>
<td style="text-align: center">默认不启用，<strong>/foo</strong>和<strong>/foo/</strong>被路由一样对待处理</td>
<td style="text-align: center">&nbsp;</td>
</tr>
</tbody>
</table>

<p>你可以将<strong>router</strong>当作一个程序，可以在其上添加中间件和HTTP路由方法(例如<strong>get</strong>，<strong>put</strong>，<strong>post</strong>等等)。</p>

<pre>
// invoked for any requests passed to this router
router.use(function(req, res, next) {
  // .. some logic here .. like any other middleware
  next();
});
// will handle any request that ends in /events
// depends on where the router is "use()'d"
router.get('/events', function(req, res, next) {
  // ..
});
</pre>

<p>你可以在一个特别的根URL上挂载一个路由，这样你就以将你的各个路由放到不同的文件中或者甚至是mini的程序。</p>

<pre>
// only requests to /calendar/* will be sent to our "router"
app.use('/calendar', router);
</pre>

<h3 id="toc_76">Methods</h3>

<h4 id="toc_77">router.all(path, [callback, ...] callback)</h4>

<p>这个方法和<strong>router.METHOD()</strong>方法一样，除了这个方法会匹配所有的HTTP动作。</p><p>
这个方法对想映射全局的逻辑处理到特殊的路径前缀或者任意匹配是十分有用的。比如，如果你放置下面所示的这个路由在其他路由的前面，那么其将要求从这个点开始的所有的路由进行验证操作和自动加载用户信息。记住，这些全局的逻辑操作，不需要结束请求响应周期：<strong>loaduser</strong>可以执行一个任务，然后调用<strong>next()</strong>来将执行流程移交到随后的路由。</p>
<pre>router.all('*', requireAuthentication, loadUser);</pre><p>
相等的形式:</p>
<pre>
router.all('*', requireAuthentication)
router.all('*', loadUser);
</pre><p>
这是一个白名单全局功能的例子。这个例子很像前面的，不过其仅仅作用于以<strong>/api</strong>开头的路径:</p>

<pre>router.all('/api/*', requireAuthentication);</pre>

<h4 id="toc_78">router.METHOD(path, [callback, ...] callback)</h4>

<p><strong>router.METHOD()</strong>方法提供了路由方法在<strong>Express</strong>中，这里的<strong>METHOD</strong>是HTTP方法中的一个，比如<strong>GET</strong>，<strong>PUT</strong>，<strong>POST</strong>等等，但<strong>router</strong>中的METHOD是小写的。所以，实际的方法是<strong>router.get()</strong>，<strong>router.put()</strong>，<strong>router.post()</strong>等等。</p><p>
你可以提供多个回调函数，它们的行为和中间件一样，除了这些回调可以通过调用<strong>next(&#39;router&#39;)</strong>来绕过剩余的路由回调。你可以使用这个机制来为一个路由设置一些前提条件，如果请求没有满足当前路由的处理条件，那么传递控制到随后的路由。</p><p>
下面的片段可能说明了最简单的路由定义。Experss转换path字符串为正则表达式，用于内部匹配传入的请求。在匹配的时候，是不考虑<strong>Query strings</strong>，例如，&quot;GET /&quot;将匹配下面的路由，&quot;GET /?name=tobi&quot;也是一样的。</p>
<pre>
router.get('/', function(req, res) {
    res.send('Hello World');
});
</pre>

<p>如果你对匹配的path有特殊的限制，你可以使用正则表达式，例如，下面的可以匹配&quot;GET /commits/71dbb9c&quot;和&quot;GET /commits/71bb92..4c084f9&quot;。</p>
<pre>
router.get(/^\/commits\/(\w+)(?:\.\.(\w+))?$/, function(req, res) {
    var from = req.params[0];
    var to = req.params[1];
    res.send('commit range ' + from + '..' + to);
});
</pre>

<h4 id="toc_79">router.param(name, callback)</h4>

<p>给路由参数添加回调触发器，这里的<strong>name</strong>是参数名，<strong>function</strong>是回调方法。回调方法的参数按序是请求对象，响应对象，下个中间件，参数值和参数名。虽然<strong>name</strong>在技术上是可选的，但是自Express V4.11.0之后版本不推荐使用(见下面)。</p>

<blockquote>
<p>不像<strong>app.param()</strong>，<strong>router.param()</strong>不接受一个数组作为路由参数。</p>
</blockquote>

<p>例如，当<strong>:user</strong>出现在路由路径中，你可以映射用户加载的逻辑处理来自动提供<strong>req.user</strong>给这个路由，或者对输入的参数进行验证。</p>
<pre>
router.param('user', function(req, res, next, id) {
    User.find(id, function(error, user) {
        if (err) {
            next(err);
        }
        else if (user){
            req.user = user;
        } else {
            next(new Error('failed to load user'));
        }
    });
});
</pre><p>
对于<strong>Param</strong>的回调定义的路由来说，他们是局部的。它们不会被挂载的app或者路由继承。所以，定义在<strong>router</strong>上的<strong>param</strong>回调只有是在<strong>router</strong>上的路由具有这个路由参数时才起作用。</p><p>
在定义<strong>param</strong>的路由上，<strong>param</strong>回调都是第一个被调用的，它们在一个请求-响应循环中都会被调用一次并且只有一次，即使多个路由都匹配，如下面的例子：</p><pre>
router.param('id', function(req, res, next, id) {
    console.log('CALLED ONLY ONCE');
    next();
});
router.get('/user/:id', function(req, res, next) {
    console.log('although this matches');
    next();
});
router.get('/user/:id', function(req, res) {
    console.log('and this mathces too');
    res.end();
});
</pre><p>
当GET /user/42，得到下面的结果:</p>
<pre>
CALLED ONLY ONCE
although this matches
and this matches too
</pre>

<blockquote>
<p>下面章节描述的<strong>router.param(callback)</strong>在v4.11.0之后被弃用。</p>
</blockquote>

<p>通过只传递一个回调参数给<strong>router.param(name, callback)</strong>方法，<strong>router.param(naem, callback)</strong>方法的行为将被完全改变。这个回调参数是关于<strong>router.param(name, callback)</strong>该具有怎样的行为的一个自定义方法，这个方法必须接受两个参数并且返回一个中间件。</p><p>
这个回调的第一个参数就是需要捕获的url的参数名，第二个参数可以是任一的JavaScript对象，其可能在实现返回一个中间件时被使用。
这个回调方法返回的中间件决定了当URL中包含这个参数时所采取的行为。</p><p>
在下面的例子中，<strong>router.param(name, callback)</strong>参数签名被修改成了<strong>router.param(name, accessId)</strong>。替换接受一个参数名和回调，<strong>router.param()</strong>现在接受一个参数名和一个数字。</p>
<pre>
var express = require('express');
var app = express();
var router = express.Router();
router.param(function(param, option){
    return function(req, res, next, val) {
        if (val == option) {
            next();
        }
        else {
            res.sendStatus(403);
        }
    }
});
router.param('id', 1337);
router.get('/user/:id', function(req, res) {
    res.send('Ok');
});
app.use(router);
app.listen(3000, function() {
    console.log('Ready');
}); 
</pre><p>
在这个例子中，router.param(name. callback)参数签名保持和原来一样，但是替换成了一个中间件，定义了一个自定义的数据类型检测方法来检测user id的类型正确性。
</p>
<pre>
router.param(function(param, validator) {
    return function(req, res, next, val) {
        if (validator(val)) {
            next();
        }
        else {
            res.sendStatus(403);
        }
    }
});
router.param('id', function(candidate) {
    return !isNaN(parseFloat(candidate)) &amp;&amp; isFinite(candidate);
});
</pre>

<h4 id="toc_80">router.route(path)</h4>

<p>返回一个单例模式的路由的实例，之后你可以在其上施加各种HTTP动作的中间件。使用<strong>router.route()</strong>来避免重复路由名字(例如错字错误)--说的意思应该是使用<strong>router.route()</strong>这个单例方法来避免同一个路径多个路由实例。</p>

<p>构建在上面的<strong>router.param()</strong>例子之上，下面的代码展示了怎么使用<strong>router.route()</strong>来指定各种HTTP方法的处理句柄。</p>
<pre>
var router = express.Router();
router.param('user_id', function(req, res, next, id) {
    // sample user, would actually fetch from DB, etc...
    req.user = {
        id:id,
        name:"TJ"
    };
    next();
});
router.route('/users/:user_id')
    .all(function(req, res, next) {
        // runs for all HTTP verbs first
        // think of it as route specific middleware!
        next();
    })
    .get(function(req, res, next) {
        res.json(req.user);
    })
    .put(function(req, res, next) {
        // just an example of maybe updating the user
        req.user.name = req.params.name;
        // save user ... etc
        res.json(req.user);
    })
    .post(function(req, res, next) {
        next(new Error('not implemented'));
    })
    .delete(function(req, res, next) {
        next(new Error('not implemented'));
    })
</pre>


<p>
这种方法重复使用单个</strong>/usrs/:user</em>id路径来添加了各种的HTTP方法。</p>

<h4 id="toc_81">router.use([path], [function, ...] function)</h4>

<p>给可选的<strong>path</strong>参数指定的路径挂载给定的中间件方法，未指定<strong>path</strong>参数，默认值为<strong>/</strong>。
这个方法类似于<strong>app.use()</strong>。一个简单的例子和用例在下面描述。查阅<a href="#toc_25">app.use()</a>获得更多的信息。</p><p>
中间件就像一个水暖管道，请求在你定义的第一个中间件处开始，顺着中间件堆栈一路往下，如果路径匹配则处理这个请求。</p>


<pre>
var express = require('express');
var app = express();
var router = express.Router();
// simple logger for this router`s requests
// all requests to this router will first hit this middleware
router.use(function(req, res, next) {
    console.log('%s %s %s', req.method, req.url, req.path);
    next();
})
// this will only be invoked if the path starts with /bar form the mount ponit
router.use('/bar', function(req, res, next) {
    // ... maybe some additional /bar logging ...
    next();
})
// always be invoked
router.use(function(req, res, next) {
    res.send('hello world')；
})
app.use('/foo', router);
app.listen(3000);
</pre>

<p>对于中间件function，挂载的路径是被剥离的和不可见的。关于这个特性主要的影响是对于不同的路径，挂载相同的中间件可能对代码不做改动，尽管其前缀已经改变。</p><p>
你使用router.use()定义中间件的顺序很重要。中间们是按序被调用的，所以顺序决定了中间件的优先级。例如，通常日志是你将使用的第一个中间件，以便每一个请求都被记录。
</p>
<pre>
var logger = require('morgan');
router.use(logger());
router.use(express.static(__dirname + '/public'));
router.use(function(req, res) {
    res.send('Hello');
});
</pre>

<p>现在为了支持你不希望记录静态文件请求，但为了继续记录那些定义在<strong>logger()</strong>之后的路由和中间件。你可以简单的将<strong>static()</strong>移动到前面来解决：</p>
<pre>
router.use(express.static(__dirname + '/public'));
router.use(logger());
router.use(function(req, res){
  res.send('Hello');
});
</pre><p>
另外一个确凿的例子是从不同的路径托管静态文件，你可以将<strong>./public</strong>放到前面来获得更高的优先级:</p>
<pre>
app.use(express.static(__dirname + '/public'));
app.use(express.static(__dirname + '/files'));
app.use(express.static(__dirname + '/uploads'));
</pre><p>
<strong>router.use()</strong>方法也支持命名参数，以便你的挂载点对于其他的路由而言，可以使用命名参数来进行预加载，这样做是很有益的。</p>


<blockquote><p>原文地址：https://github.com/bajian/express_api_4.x_chinese</p></blockquote>


				</div>
			</div>
			<div class="previous-next-links">
			<div class="previous-design-link">← <a href="../w3cnote/python-understanding-dict-copy-shallow-or-deep.html" rel="prev"> Python 直接赋值、浅拷贝和深度拷贝解析</a> </div>
			<div class="next-design-link"><a href="../w3cnote/node-multi-version.html" rel="next"> 手把手告诉你如何安装多个版本的node</a> →</div>
			</div>
						<div class="article-heading-ad" id="w3cnote-ad728">
			<script async src=""></script>
			<!-- 移动版 自动调整 -->
			<ins class="adsbygoogle"
			     style="display:inline-block;min-width:300px;max-width:970px;width:100%;height:90px"
			     data-ad-client="ca-pub-5751451760833794"
			     data-ad-slot="1691338467"
			     data-ad-format="horizontal"></ins>
			<script>
			(adsbygoogle = window.adsbygoogle || []).push({});
			</script>
			</div>
			<style>
@media screen and (max-width: 768px) {
	#w3cnote-ad728 {
		display: none;
	}
}
p.note-author {
    border-bottom: 1px solid #ddd;
    font-size: 18px;
    font-weight: bold;
    color: #78a15a;
    padding-bottom: 2px;
    margin-bottom: 4px;
}
</style>
<script>
var aid = 18584;
</script>
	</div>
		
	</div>
	<div class="listcol last right-column">




<!--
	<div class="tab tab-light-blue"> 订阅</div>
	<div class="sidebar-box">
		<div class="socialicons">
			<a href="../feed" class="rss">RSS 订阅</a>
		
			<form action="//list.qq.com/cgi-bin/qf_compose_send" method="post">
			<input type="hidden" value="qf_booked_feedback" name="t">
			<input type="hidden" value="4b67b6b6c1f5e792559940cab4aebb8f1126fba880bff1a8" name="id">
			<input class="placeholder" id="feed_email" name="to" value="输入邮箱 订阅笔记" autocomplete="off">
			<input type="submit" value="订阅" class="btn btn-primary">
			</form>
		
		</div>
 
	</div>
-->	



<!--
	<div class="sidebar-box cate-list">
	<div class="sidebar-box recommend-here list-link">
			<a href="javascript:void(0);" style="font-size: 16px; color:#64854c;font-weight:bold;">笔记列表</a>
		</div>

 

</div>
-->

	 <div class="sidebar-box cate-list">
		 		

	 	<div class="sidebar-box recommend-here list-link">
			<a href="javascript:void(0);" style="font-size: 16px; color:#64854c;font-weight:bold;">教程列表</a>
		</div>
		
		<div class="cate-items"> 
				<a href="../ado">ADO 教程</a>
	<a href="../ajax">Ajax 教程</a>
	<a href="../android">Android 教程</a>
	<a href="../angularjs2">Angular2 教程</a>
	<a href="../angularjs">AngularJS 教程</a>
	<a href="../appml">AppML 教程</a>
	<a href="../asp">ASP 教程</a>
	<a href="../aspnet">ASP.NET 教程</a>
	<a href="../bootstrap">Bootstrap 教程</a>
	<a href="../bootstrap4">Bootstrap4 教程</a>
	<a href="../bootstrap5">Bootstrap5 教程</a>
	<a href="../cprogramming">C 教程</a>
	<a href="../csharp">C# 教程</a>
	<a href="../cplusplus">C++ 教程</a>
	<a href="../chartjs">Chart.js 教程</a>
	<a href="../cssref">CSS 参考手册</a>
	<a href="../css">CSS 教程</a>
	<a href="../css3">CSS3 教程</a>
	<a href="../django">Django 教程</a>
	<a href="../docker">Docker 教程</a>
	<a href="../dtd">DTD 教程</a>
	<a href="../echarts">ECharts 教程</a>
	<a href="../eclipse">Eclipse 教程</a>
	<a href="../firebug">Firebug 教程</a>
	<a href="../font-awesome">Font Awesome 图标</a>
	<a href="../foundation">Foundation 教程</a>
	<a href="../git">Git 教程</a>
	<a href="../go">Go 语言教程</a>
	<a href="../googleapi">Google 地图 API 教程</a>
	<a href="../highcharts">Highcharts 教程</a>
	<a href="../htmldom">HTML DOM 教程</a>
	<a href="../tags">HTML 参考手册</a>
	<a href="../charsets">HTML 字符集</a>
	<a href="../html">HTML 教程</a>
	<a href="../http">HTTP 教程</a>
	<a href="../ionic">ionic 教程</a>
	<a href="../ios">iOS 教程</a>
	<a href="../java">Java 教程</a>
	<a href="../jsref">JavaScript 参考手册</a>
	<a href="../js">Javascript 教程</a>
	<a href="../jeasyui">jQuery EasyUI 教程</a>
	<a href="../jquerymobile">jQuery Mobile 教程</a>
	<a href="../jqueryui">jQuery UI 教程</a>
	<a href="../jquery">jQuery 教程</a>
	<a href="../json">JSON 教程</a>
	<a href="../jsp">JSP 教程</a>
	<a href="../julia">Julia 教程</a>
	<a href="../kotlin">Kotlin 教程</a>
	<a href="../linux">Linux 教程</a>
	<a href="../lua">Lua 教程</a>
	<a href="../markdown">Markdown 教程</a>
	<a href="../matplotlib">Matplotlib 教程</a>
	<a href="../maven">Maven 教程</a>
	<a href="../memcached">Memcached 教程</a>
	<a href="../mongodb">MongoDB 教程</a>
	<a href="../mysql">MySQL 教程</a>
	<a href="../nodejs">Node.js 教程</a>
	<a href="../numpy">NumPy 教程</a>
	<a href="../pandas">Pandas 教程</a>
	<a href="../perl">Perl 教程</a>
	<a href="../php">PHP 教程</a>
	<a href="../postgresql">PostgreSQL 教程</a>
	<a href="../python3">Python 3 教程</a>
	<a href="../python">Python 基础教程</a>
	<a href="../r">R 教程</a>
	<a href="../rdf">RDF 教程</a>
	<a href="../react">React 教程</a>
	<a href="../redis">Redis 教程</a>
	<a href="../rss">RSS 教程</a>
	<a href="../ruby">Ruby 教程</a>
	<a href="../rust">Rust 教程</a>
	<a href="../sass">Sass 教程</a>
	<a href="../scala">Scala 教程</a>
	<a href="../scipy">SciPy 教程</a>
	<a href="../servlet">Servlet 教程</a>
	<a href="../soap">SOAP 教程</a>
	<a href="../sql">SQL 教程</a>
	<a href="../sqlite">SQLite 教程</a>
	<a href="../svg">SVG 教程</a>
	<a href="../svn">SVN 教程</a>
	<a href="../swift">Swift 教程</a>
	<a href="../tcpip">TCP/IP 教程</a>
	<a href="../typescript">TypeScript 教程</a>
	<a href="../vbscript">VBScript 教程</a>
	<a href="../vue2">Vue.js 教程</a>
	<a href="../vue3">Vue3 教程</a>
	<a href="../w3c">W3C 教程</a>
	<a href="../webservices">Web Service 教程</a>
	<a href="../wsdl">WSDL 教程</a>
	<a href="../xlink">XLink 教程</a>
	<a href="../dom">XML DOM 教程</a>
	<a href="../schema">XML Schema 教程</a>
	<a href="../xml">XML 教程</a>
	<a href="../xpath">XPath 教程</a>
	<a href="../xquery">XQuery 教程</a>
	<a href="../xslfo">XSLFO 教程</a>
	<a href="../xsl">XSLT 教程</a>
	<a href="../data-structures">数据结构</a>
	<a href="../regexp">正则表达式</a>
	<a href="../quiz">测验</a>
	<a href="../browsers">浏览器</a>
	<a href="../quality">网站品质</a>
	<a href="../web">网站建设指南</a>
	<a href="../hosting">网站服务器教程</a>
	<a href="../design-pattern">设计模式</a>
			
		</div> 
		 	 </div>
</div>
	</div>
</div>


<!-- 底部 -->
<div id="footer" class="mar-t50">
   <div class="runoob-block">
    <div class="runoob cf">
     <dl>
      <dt>
       在线实例
      </dt>
      <dd>
       &middot;<a target="_blank" href="../html/html-examples.html">HTML 实例</a>
      </dd>
      <dd>
       &middot;<a target="_blank" href="../css/css-examples.html">CSS 实例</a>
      </dd>
      <dd>
       &middot;<a target="_blank" href="../js/js-examples.html">JavaScript 实例</a>
      </dd>
      <dd>
       &middot;<a target="_blank" href="../ajx/ajax-examples.html">Ajax 实例</a>
      </dd>
       <dd>
       &middot;<a target="_blank" href="../jquery/jquery-examples.html">jQuery 实例</a>
      </dd>
      <dd>
       &middot;<a target="_blank" href="../xml/xml-examples.html">XML 实例</a>
      </dd>
      <dd>
       &middot;<a target="_blank" href="../java/java-examples.html">Java 实例</a>
      </dd>
     
     </dl>
     <dl>
      <dt>
      字符集&工具
      </dt>
      <dd>
       &middot; <a target="_blank" href="../charsets/html-charsets.html">HTML 字符集设置</a>
      </dd>
      <dd>
       &middot; <a target="_blank" href="../tags/html-ascii.html">HTML ASCII 字符集</a>
      </dd>
     <dd>
       &middot; <a target="_blank" href="https://c.runoob.com/front-end/6939/">JS 混淆/加密</a>
      </dd> 
      <dd>
       &middot; <a target="_blank" href="https://c.runoob.com/front-end/6232/">PNG/JPEG 图片压缩</a>
      </dd>
      <dd>
       &middot; <a target="_blank" href="../tags/html-colorpicker.html">HTML 拾色器</a>
      </dd>
      <dd>
       &middot; <a target="_blank" href="..//c.runoob.com/front-end/53">JSON 格式化工具</a>
      </dd>
      <dd>
       &middot; <a target="_blank" href="..//c.runoob.com/front-end/6680/">随机数生成器</a>
      </dd>
     </dl>
     <dl>
      <dt>
       最新更新
      </dt>
                   <dd>
       &middot;
      <a href="../matplotlib/matplotlib-imread.html" title="Matplotlib imread() 方法">Matplotlib imre...</a>
      </dd>
              <dd>
       &middot;
      <a href="../matplotlib/matplotlib-imsave.html" title="Matplotlib imsave() 方法">Matplotlib imsa...</a>
      </dd>
              <dd>
       &middot;
      <a href="../matplotlib/matplotlib-imshow.html" title="Matplotlib imshow() 方法">Matplotlib imsh...</a>
      </dd>
              <dd>
       &middot;
      <a href="../matplotlib/matplotlib-hist.html" title="Matplotlib 直方图">Matplotlib 直方图</a>
      </dd>
              <dd>
       &middot;
      <a href="../python3/python-func-object.html" title="Python object() 函数">Python object()...</a>
      </dd>
              <dd>
       &middot;
      <a href="../python3/python-ai-draw.html" title="Python AI 绘画">Python AI 绘画</a>
      </dd>
              <dd>
       &middot;
      <a href="../w3cnote/cursor-editor.html" title="神辅助 Cursor 编辑器，加入 GPT-4 让编码更轻松！">神辅助 Cursor ...</a>
      </dd>
             </dl>
     <dl>
      <dt>
       站点信息
      </dt>
      <dd>
       &middot;
       <a target="_blank" href="mailto:admin@runoob.com" rel="external nofollow">意见反馈</a>
       </dd>
      <dd>
       &middot;
      <a target="_blank" href="../disclaimer">免责声明</a>
       </dd>
      <dd>
       &middot;
       <a target="_blank" href="../aboutus">关于我们</a>
       </dd>
      <dd>
       &middot;
      <a target="_blank" href="../archives">文章归档</a>
      </dd>
    
     </dl>
    
     <div class="search-share">
      <div class="app-download">
        <div>
         <strong>关注微信</strong>
        </div>
      </div>
      <div class="share">
      <img width="128" height="128" src="/wp-content/themes/runoob/assets/images/qrcode.png" />
       </div>
     </div>
     
    </div>
   </div>
   <div class="w-1000 copyright">
     Copyright &copy; 2013-2023    <strong><a href="../" target="_blank">菜鸟教程</a></strong>&nbsp;
    <strong><a href="../" target="_blank">runoob.com</a></strong> All Rights Reserved. 备案号：<a target="_blank" rel="nofollow" href="https://beian.miit.gov.cn/">闽ICP备15012807号-1</a>
   </div>
  </div>
  <div class="fixed-btn">
    <a class="go-top" href="javascript:void(0)" title="返回顶部"> <i class="fa fa-angle-up"></i></a>
    <a class="qrcode"  href="javascript:void(0)" title="关注我们"><i class="fa fa-qrcode"></i></a>
    <a class="writer" style="display:none" href="javascript:void(0)"   title="标记/收藏"><i class="fa fa-star" aria-hidden="true"></i></a>
    <!-- qrcode modal -->
    <div id="bottom-qrcode" class="modal panel-modal hide fade in">
      <h4>微信关注</h4>
      <div class="panel-body"><img alt="微信关注" width="128" height="128" src="/wp-content/themes/runoob/assets/images/qrcode.png"></div> 
    </div>
  </div>

 <div style="display:none;">
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-84264393-2"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'UA-84264393-2');
</script>
<script>
var _hmt = _hmt || [];
(function() {
  var hm = document.createElement("script");
  hm.src = "https://hm.baidu.com/hm.js?3eec0b7da6548cf07db3bc477ea905ee";
  var s = document.getElementsByTagName("script")[0]; 
  s.parentNode.insertBefore(hm, s);
})();
</script>

</div>
<script>
window.jsui={
    www: 'https://www.runoob.com',
    uri: 'https://www.runoob.com/wp-content/themes/runoob'
};
</script>

<script src=""></script>
<script src=""></script>

</body>
</html>